Codeforces 305E Playing with String 博弈

我们可以把每段连续可以选的字符看成一个游戏, 那么sg[ i ]表示连续 i 个字符可选的sg值。

然后找找第一个就好啦。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 5000 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-13;
const double PI = acos(-1);

int sg[N], n;
bool mex[N];
char s[N];

int calc(int l, int r) {
    int cnt = 0, ans = 0;
    for(int i = l + 1; i < r; i++) {
        if(s[i - 1] == s[i + 1]) {
            cnt++;
        } else {
            ans ^= sg[cnt];
            cnt = 0;
        }
    }
    ans ^= sg[cnt];
    return ans;
}

int main() {
    sg[0] = 0; sg[1] = 1; sg[2] = 1;
    for(int i = 3; i < N; i++) {
        memset(mex, 0, sizeof(mex));
        for(int j = 1; j <= i; j++)
            mex[sg[max(0, j - 2)] ^ sg[max(0, i - j - 1)]] = true;
        for(int j = 0; ; j++) {
            if(!mex[j]) {
                sg[i] = j;
                break;
            }
        }
    }

    scanf("%s", s + 1);
    n = strlen(s + 1);

    int ans = 0, cnt = 0;
    for(int i = 1; i <= n; i++) {
        if(s[i - 1] == s[i + 1]) cnt++;
        else {
            ans ^= sg[cnt];
            cnt = 0;
        }
    }
    if(!ans) {
        puts("Second");
    } else {
        puts("First");
        for(int i = 1; i <= n; i++) {
            if(s[i - 1] == s[i + 1]) {
                if(!(calc(1, i - 1) ^ calc(i + 1, n))) {
                    printf("%d
", i);
                    return 0;
                }
            }
        }
    }
    return 0;
}

/*

*/
原文地址:https://www.cnblogs.com/CJLHY/p/10612346.html