#博弈论,SG函数#洛谷 4077 [SDOI2016] 硬币游戏
分析
首先,不同的 \(c\) 是独立且等价的,设计 SG 函数,\(SG(MAXQ,a,b)\),
枚举 \(p,q\) 求出后继状态的 SG 值求 MEX 即可,要注意后继状态的 SG 值是 SG 函数的异或和(比如 \(SG(MAXQ,a,b-q)\text{ xor }SG(MAXQ,a,b-2q)\))。
代码
#include <iostream>
#include <string>
using namespace std;
const int N=30001,M=21;
int two[N],three[N],sg[M][M][M],Test,n,m,ans;
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
for (int i=1;i<N;++i){
if (i%2==0) two[i]=two[i>>1]+1;
if (i%3==0) three[i]=three[i/3]+1;
}
for (int o=1;o<M;++o)
for (int i=0,I=1;I<N;I<<=1,++i)
for (int j=0,J=1;J*I<N;J*=3,++j){
int ans=0;
for (int p=1;p<=i;++p){
int now=0;
for (int q=1;p*q<=i&&q<=o;++q)
now^=sg[o][i-p*q][j],ans|=1<<now;
}
for (int p=1;p<=j;++p){
int now=0;
for (int q=1;p*q<=j&&q<=o;++q)
now^=sg[o][i][j-p*q],ans|=1<<now;
}
sg[o][i][j]=__builtin_ctz(~ans);
}
for (cin>>Test;Test;--Test){
cin>>n>>m,ans=0;
for (int i=1,x;i<=n;++i){
cin>>x;
if (!x) ans^=sg[m][two[i]][three[i]];
}
if (ans) cout<<"win\n";
else cout<<"lose\n";
}
return 0;
}

浙公网安备 33010602011771号