P2197 【模板】Nim 游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思路:最模板的SG函数.
因为可以取1到x个石子,那么x的后继状态为[0,x-1],那么sg(x)=x.
int n;
P2197 【模板】Nim 游戏
https://www.luogu.com.cn/problem/P2197
void solve(){
cin>>n;
int ans=0;
for(int i=1;i<=n;i++){ 因为可以取1到x个石子,那么x的后继状态为[0,x-1],那么sg(x)=x.
int x; cin>>x;
ans^=x;
}
if(ans!=0) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
C-小w和大W的决斗。_河南萌新联赛2024第(二)场:南阳理工学院 (nowcoder.com)
思路:
枚举x的后继状态和枚举x的后继三种子游戏状态。暴力求SG值。
int n;
int sg[105]; 石头堆大小为i的sg值为sg[i].
int getSG(int x){
if(sg[x]!=-1) return sg[x];
vector<int> vis(105,0);
for(int i=0;i<x;i++){ 枚举x的后继状态
vis[getSG(i)]=1;
}
for(int i=1;i<x;i++){ 枚举x的后继三种子游戏状态
for(int j=1;j+i<x;j++){
int k=x-i-j;
vis[getSG(i)^getSG(j)^getSG(k)]=1;
}
}
int mex=0;
while(vis[mex]) mex++;
return sg[x]=mex;
}
问题:sg怎么处理分成三堆的操作? 枚举x的后继三种子游戏状态
小w和大W的决斗。 题目没说清楚..i+j+k=x,是分成3个"非空"的堆
https://ac.nowcoder.com/acm/contest/87255/C
void solve(){ 模板题
for(int i=0;i<=100;i++) sg[i]=-1; init;
sg[0]=0;
getSG(100);
cin>>n;
int ans=0;
for(int i=1;i<=n;i++){
int x; cin>>x;
ans^=sg[x];
}
if(ans!=0) cout<<"w win"<<endl;
else cout<<"W win"<<endl;
}
[ABC297G] Constrained Nim 2 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思路:
这题有2e5堆石子,每堆石子有1e9个石头,每次可以取[l,r]个,并且l,r取值最大也是1e9。数据范围这么大怎么求sg? 不能暴力求了,得推导公式(not easy)..或者暴力求sg打表找规律(更可能实现) 通过打表找规律发现,不同的l,r,计算sg(x)的公式为sg(x)=(x%(l+r))/l; 规律..不好发现..但是也不是说完全不能发现...循环的部分x%(l+r)是好发现的.但是除以l就没发觉了..
int n,l,r;
int sg[55];
int getSG(int x){
if(sg[x]!=-1) return sg[x];
vector<int> vis(55,0);
for(int i=max(x-r,0ll);i<=x-l;i++) vis[getSG(i)]=1;
int mex=0;
while(vis[mex]) mex++;
return sg[x]=mex;
}
这题有2e5堆石子,每堆石子有1e9个石头,每次可以取[l,r]个,并且l,r取值最大也是1e9。数据范围这么大怎么求sg?
不能暴力求了,得推导公式(not easy)..或者暴力求sg打表找规律(更可能实现)
通过打表找规律发现,不同的l,r,计算sg(x)的公式为sg(x)=(x%(l+r))/l;
规律..不好发现..但是也不是说完全不能发现...循环的部分x%(l+r)是好发现的.但是除以l就没发觉了..
[ABC297G] Constrained Nim 2
https://www.luogu.com.cn/problem/AT_abc297_g
void solve(){ nim
// cin>>l>>r;
// for(int i=0;i<=50;i++) sg[i]=-1; init
// sg[0]=0;
// for(int i=1;i<=50;i++) getSG(i);
// for(int i=0;i<=50;i++) cout<<sg[i]<<" ";
cin>>n>>l>>r;
int ans=0;
for(int i=1;i<=n;i++){
int x; cin>>x;
ans^=( (x%(l+r))/l );
}
if(ans!=0) cout<<"First";
else cout<<"Second";
}
P2252 [SHOI2002] 取石子游戏|【模板】威佐夫博弈 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
思路:这个不是SG函数,记结论吧。
奇异局势:小堆的个数等于两堆的差值*(sqrtl(5.0)+1.0)/2.0--注意开long double
P2252 [SHOI2002] 取石子游戏|【模板】威佐夫博弈--奇异局势:A=(B-A)*(sqrt(5)+1)/2 A是小堆石头个数,B为大堆
奇异局势:小堆的个数等于两堆的差值*(sqrtl(5.0)+1.0)/2.0
https://www.luogu.com.cn/problem/P2252
void solve(){
int A,B; cin>>A>>B;
if(A>B) swap(A,B);
int Z=B-A;
long double wyf=(sqrtl(5.0)+1.0)/2.0; 开long double,并且用sqrtl求根号!
if(A==(int)(wyf*(double)Z)) cout<<"0";
else cout<<"1";
}