一般 Nim 游戏基础上增加
显然博弈论,考虑 SG函数。Nim 游戏标准套路,对于多个石子堆求出每个石子堆石子数
本题的区别即为 map 记录转折点,每次查询对应的所在位置然后增加对应数量的
具体实现过程也不难理解,开个 map 里套 basic_string 维护对应
xxxxxxxxxx77123
45678910
11using namespace std;12
13mt19937 rnd(random_device{}());14int rndd(int l, int r){return rnd() % (r - l + 1) + l;}15bool rnddd(int x){return rndd(1, 100) <= x;}16
17typedef unsigned int uint;18typedef unsigned long long unll;19typedef long long ll;20typedef long double ld;21
22template < typename T = int >23inline T read(void);24
25int N, M;26ll A[210000];27ll oplus(0);28map < ll, basic_string < ll > > rest;29map < ll, ll > SG, repeat;30
31ll CalSG(ll x){32 auto sp = *prev(SG.upper_bound(x));33 return sp.second + (x - sp.first);34}35
36int main(){37 N = read(), M = read(); SG.insert({0, 0});38 for(int i = 1; i <= N; ++i)A[i] = read < ll >();39 for(int i = 1; i <= M; ++i){40 ll p = read < ll >(), v = read < ll >();41 rest[p] += p - v;42 }43 ll preMx(-1);44 for(auto &mp : rest){45 preMx = max(preMx, CalSG(mp.first - 1));46 map < ll, ll > tmp;47 for(auto val : mp.second)tmp[CalSG(val)]++;48 for(auto cur : tmp){49 if(cur.second >= repeat[cur.first] + 1){50 repeat[cur.first]++;51 SG[mp.first] = cur.first;52 break;53 }54 }preMx = max(preMx, CalSG(mp.first));55 SG[mp.first + 1] = preMx + 1;56 }57 for(int i = 1; i <= N; ++i)oplus ^= CalSG(A[i]);58 printf("%s\n", oplus ? "Takahashi" : "Aoki");59 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);60 return 0;61}62
63template < typename T >64inline T read(void){65 T ret(0);66 int flag(1);67 char c = getchar();68 while(c != '-' && !isdigit(c))c = getchar();69 if(c == '-')flag = -1, c = getchar();70 while(isdigit(c)){71 ret *= 10;72 ret += int(c - '0');73 c = getchar();74 }75 ret *= flag;76 return ret;77}update-2022_12_07 初稿