【数论学习笔记】 NIM游戏
博弈论的内容。
游戏规则:
地上有n堆石子,每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。
每次只能从一堆里取。最后没石子可取的人就输了。
先手是先操作的人。
定理:先手必胜 当且仅当 A1 xor A2 xor A3……!= 0。
证明:当所有物品都取光。明显为A1 xor A2 xor A3……= 0。
如果A1 xor A2 xor A3……= x != 0。假设最高位1在第k位。
必然有至少一堆石子Ai 第k为1。
Ai xor x < x。(第k位为0了。)
这样就从Ai 中取出石子,使得新的序列A1 xor A2 xor A3……= 0。后手必定无法取。(先手可以一直和后手取一样多的石子维护这个序列异或等于零。)
例题:
luogu:P1247:https://www.luogu.org/problemnew/show/P1247
P2197:https://www.luogu.org/problemnew/show/P2197
P1247代码如下。
#include<bits/stdc++.h> using namespace std; int n,c=0; int a[500005]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); c^=a[i]; } if(c==0){ printf("lose\n"); return 0; } for(int i=1;i<=n;i++){ if((c^a[i])<a[i]){ printf("%d %d\n",a[i]-(c^a[i]),i); for(int j=1; j<=n; j++) if(j!=i) printf("%d ",a[j]); else printf("%d ",c^a[i]); break; } } // while(1); return 0; }