sg博弈
首先写个SG打表程序
#include<cstdio>
#include<stdlib.h>
#include<cstring>
#include<queue>
using namespace std;
int sg[110],k;
int find(int i){
if(sg[i]!=-1)return sg[i];
int use[100],j;
memset(use,0,sizeof(use));
for(j=1;j<=i;j*=k)
use[find(i-j)]=1;
j=0;
while(use[j])j++;
return sg[i]=j;
}
int main(){
int n,i;
scanf("%d",&k);
memset(sg,-1,sizeof(sg));
for(i=1;i<=100;i++){
printf("%d %d\n",i,find(i));
}
}
然后可以发现规律,当k为奇数时,1,0,1,0,1,0。。。。这样变化,故n为奇数只需移走1个石头,而n为偶数必败
当k为偶数时,SG表是一个k+1的循环,比如k=4时,1,0,1,2,0,1,0,1,2,0.。。。故分析可知sg值为0的必败,sg值为1的只需要移走1个石头,sg值为2时,如果移走一个,则走到sg为1的点上还是必败,而移动k个石子易知可到达必胜态
AC程序
#include<cstdio>
#include<stdlib.h>
#include<cstring>
#include<queue>
using namespace std;
int main(){
int i,t,T,k,s;
scanf("%d",&T);
for(t=1;t<=T;t++){
scanf("%d %d",&s,&k);
if(k&1){
if(s&1)printf("1\n");
else printf("0\n");
}
else{
int tem=s%(k+1);
if(tem==k)printf("%d\n",k);
else{
if(tem&1)printf("1\n");
else printf("0\n");
}
}
}
}