51Nod 1831 小C的游戏

来源:互联网 发布:什么东西淘宝没有卖 编辑:程序博客网 时间:2024/05/17 15:19

博弈论+打表

首先吐槽一下题面,【把这个石子堆分成等量的几份并只取其中一份】是说只留下其中一份而不是去掉其中一份!被坑很久,所以题目描述可以不那么随便吗…?

然后xjb打表,质数基本都是败,合数基本都是胜,但有一些例外。

题解是这么说的:

最简单的做法就是找规律了,直接搜一下就能获得所有的胜负态。
仔细观察可以发现质数除了2和17就是败的,合数除了16,34和289都是赢的。
感觉这样是不太科学的,那就来讲讲道理。
我们发现2,4,8都是赢的,而16的后继状态都是赢的,所以它是败的,而2^n(n>4)都能转化到16。
同样的我们能说明17和2^n17^m。
我们考虑一个合数,它的因数肯定有个败态的,它就必胜了。
这样也就说明了质数是必败了。

这样证明真的好吗……

附代码(包括打表)

#include<cstdio>#include<cmath>#include<cstring>#include<algorithm> #define N 2333 #define ll long longusing namespace std;namespace runzhe2000{    /*以下打表找规律*/    int a[N][N], n;    bool dfs(int x)    {        int have = 0; for(int i = 1; i <= n; i++) if(a[x][i]) {have = 1; break;} if(!have) return 1;        for(int i = 1; i <= n; i++) if(a[x][i])        {            memcpy(a[x+1], a[x], sizeof(a[x]));             a[x+1][i]--; sort(a[x+1]+1, a[x+1]+n+1);            if(!dfs(x+1)) return 1;        }        for(int i = 1; i <= n; i++) if(a[x][i])        {            for(int j = 2; j < a[x][i]; j++) if(a[x][i] % j == 0)            {                memcpy(a[x+1], a[x], sizeof(a[x]));                 a[x+1][i] = j;                sort(a[x+1]+1, a[x+1]+n+1);                if(!dfs(x+1)) return 1;            }         }        return 0;    }    void solve(int nn)    {        memset(a,0,sizeof(a));        n = nn; a[1][n] = n;  bool nop = 0; int tmp = dfs(1);        for(int i = 2; i < nn; i++)  if(nn % i == 0) nop = 1;        printf("%d(%d) : %d --> %d\n",nn,nop?0:1,tmp?1:0,(nop==tmp));    }    void check(int lim)    {        for(int i = 1; i <= lim; i++)             solve(i);    }    /*以上打表找规律*/    void main()    {//      check(300);             int T; scanf("%d",&T);         for(; T--; )        {            int n, nop = 0; scanf("%d",&n);             for(int i = 2, ii = sqrt(n); i <= ii; i++) if(n % i == 0) {nop = 1; break;}            if(!nop) {puts(n==2||n==17?"TAK":"NIE");}            else puts(n==16||n==34||n==289?"NIE":"TAK");        }    }}int main(){    runzhe2000::main();}
0 0
原创粉丝点击