标签:个数 策略 nim size else http clu color []
https://scut.online/p/290
一个 N 个数的取数游戏,Kaildls 和 Parco 轮流操作,每次操作从 N 个数中取一个数 y 并把他变成 y-x(满足 x | y 且x < y),无法操作的人输。
假设 Kaildls 先手且两人都是用最优策略,请问最后谁会赢?
第一次学SG函数,要找的是每次能从石子堆中取走的数目,记录下来。
最后的Nim和为0是后手赢?
#include<bits/stdc++.h> using namespace std; #define ll long long #define MAXN 1000005 #define N 1000005 //f[N]:可改变当前状态的方式,N为方式的种类,f[N]要在getSG之前先预处理 //SG[]:0~n的SG函数值 //S[]:为x后继状态的集合 vector<int> nextofSG[MAXN]; int f[N],SG[MAXN],S[MAXN]; void getSG(int n){ for(int i = 2; i <= n; i++){ int l=nextofSG[i].size(); //后继状态 最多有l 种 for(int j=0;j<=l;j++){ S[j]=0; } for(auto vi:nextofSG[i]){ //vi:从i状态能取走的石子数 S[SG[i-vi]]=1; } for(int j=0;j<=l;j++){ if(!S[j]){ SG[i] = j; break; } } //cout<<"SG["<<i<<"]="<<SG[i]<<endl; } } int a[1000005]; unsigned generateai(unsigned &n,unsigned &x,unsigned &y, unsigned &z){ x=x^(x<<11); x=x^(x>>4); x=x^(x<<5); x=x^(x>>14); unsigned w=x^(y^z); x=y; y=z; z=w; return z; } int main(){ unsigned n,x,y,z; for(int i=1;i<=1000000;i++){ for(int j=i+i;j<=1000000;j+=i){ nextofSG[j].push_back(i); } } getSG(1000000); for(int t=0;t<100;t++){ cin>>n>>x>>y>>z; int sumSG=0; for(int i=0;i<n;i++){ a[i]=generateai(n,x,y,z)%n+1; //cout<<a[i]<<endl; sumSG^=SG[a[i]]; } //cout<<"!"<<sumSG<<endl; if(sumSG==0) cout<<"Parco"<<endl; else{ cout<<"Kaildls"<<endl; } } }
标签:个数 策略 nim size else http clu color []
原文地址:https://www.cnblogs.com/Yinku/p/10421254.html