题解 P4077 【[SDOI2016]硬币游戏】
如果换成下面这个游戏,是不是一眼可以看出是
①开始有一些地方有石子
②每次可以选择满足条件的
注意到这个问题对每个数是独立的,应用
那么回到原游戏,我们发现原游戏就是这个游戏
并且呢,如果某方在原游戏下有必胜策略,那么在新游戏中如果对方动了一个位置,且:
①如果这个位置原有奇数个棋子,那按原游戏里面必胜策略下就可以
②否则复读(显然可以复读,而且这样
这是新游戏的一个必胜策略
那么容易证明这两个游戏的获胜条件是相同的
那是不是直接
(注意看清题意,看清每次合法操作都是什么以防WA)
#include <bits/stdc++.h>
using namespace std;
#define maxn 33333
int n,q;
int sg[maxn];
int cnt[303]={0};
void gao(int x,int p,int w) {
int a,b,c=0,y=x;
for(a=1;a<=q;a++) {
if(y%p!=0) break;
y/=p;c^=sg[y];
if(c<303) cnt[c]=x;
}
}
void get_sg(int x) {
int a,b,c;
for(b=2,a=1;;a++) {
if(x%b!=0) break;
gao(x,b,a);
b*=2;
}
for(b=3,a=1;;a++) {
if(x%b!=0) break;
gao(x,b,a);
b*=3;
}
for(a=0;;a++)
if(cnt[a]!=x) {
sg[x]=a;
return;
}
}
int main(){
int T,t;
scanf("%d",&T);
for(t=1;t<=T;t++) {
int a,b,c=0;
memset(cnt,0,sizeof cnt);
scanf("%d%d",&n,&q);
for(a=1;a<=n;a++) get_sg(a);
//for(a=1;a<=n;a++) printf("%d\n",sg[a]);
for(a=1;a<=n;a++) {
scanf("%d",&b);
if(b==0) c^=sg[a];
}
if(c==0) printf("lose\n");
else printf("win\n");
}
return 0;
}