一般 Nim 游戏基础上增加
显然博弈论,考虑 SG函数。Nim 游戏标准套路,对于多个石子堆求出每个石子堆石子数
本题的区别即为 map
记录转折点,每次查询对应的所在位置然后增加对应数量的
具体实现过程也不难理解,开个 map
里套 basic_string
维护对应
xxxxxxxxxx
771
2
3
4
5
6
7
8
9
10
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 初稿