您的位置:首页 > 其它

51Nod 1831 小C的游戏

2017-03-18 14:29 288 查看
博弈论+打表

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

然后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 long
using namespace std;
namespace runzhe2000
{
/*以下打表找规律*/
int a

, 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;  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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: