HDU 4203

来源:互联网 发布:5.48数据库 编辑:程序博客网 时间:2024/05/20 13:38

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");            }        }    }}