您的位置:首页 > 其它

取石子(九)(十)(nyoj 888 && 913)

2014-05-28 21:48 281 查看
nyoj 888:点击打开链接

反nim 详细看这里:点击打开链接

#include <stdio.h>

int main (void)
{
int n, t;
scanf("%d", &t);
while(t --)
{
scanf("%d", &n);
int a, count = 0, sum = 0;
int i;
for(i = 0; i < n; i++)
{
scanf("%d", &a);
sum ^= a;
if(a > 1)
count++;
}
if(count == 1)//充裕堆等于1必胜
printf("Yougth\n");
else if(count >= 2 && sum != 0)//充裕堆大于2且异或和不为0必胜
printf("Yougth\n");
else if(count == 0 && sum == 0)//充裕堆为0且是偶数堆必胜
printf("Yougth\n");
else
printf("Hrdv\n");
}
return 0;
}


nyoj 913:点击打开链接

算是找规律的题吧……讲所有的sg值异或起来,结果为0先手输,否则后手输。

其中第二堆和第四堆要将所有的sg值算出来,其余堆都可以找到规律。

第一堆的sg值:

#include <stdio.h>
#include <string.h>

int sg[100];

int getsg(int n)
{
if(sg
!= -1)
return sg
;
int i;
bool vis[100];
memset(vis, 0, sizeof(vis));
for(i = 1; i <= n; i *= 2)
if(n >= i)
vis[getsg(n - i)] = 1;
for(i = 0; i < 100; i++)
if(!vis[i])
break;
return sg
= i;
}

int main (void)
{
int i;
memset(sg, -1, sizeof(sg));
sg[0] = 0;
for(i = 1; i < 100; i++)
int ok = getsg(i);
for(i = 0; i < 100; i++)
printf("%d ", sg[i]);
return 0;

}


打表结果 规律很好找:

0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0
1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1
2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0 1 2 0


第三堆就是尼姆。

第五堆sg值:

#include <stdio.h>
#include <string.h>

int sg[1010];

int getsg(int n)
{
if(sg
!= -1)
return sg
;
int i;
bool vis[1000];
memset(vis, 0, sizeof(vis));
for(i = 1; i <= 1010; i += 2)
{
if(n >= i)
vis[getsg(n - i)] = 1;
else
break;
}
for(i = 0; i < 1000; i++)
if(!vis[i])
break;
return sg
= i;
}

int main (void)
{
int i;
memset(sg, -1, sizeof(sg));
sg[0] = 0;
for(i = 1; i < 1010; i++)
int ok = getsg(i);
for(i = 0; i < 1010; i++)
printf("%d ", sg[i]);
return 0;

}


结果:

0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
0 1 0 1 0 1 0 1 0 1


第六堆及第六堆以上的,就是巴什博弈,sg值就是模(k + 1)以后的值。

第二堆和第四堆直接看最后的程序:
#include <stdio.h>
#include <string.h>
int a[20];//斐波那次数列
int sg[1010], sg2[1010];//sg-第四堆 sg2-第二堆

int getsg2(int n)
{//求sg2
if(sg2
!= -1)
return sg2
;
int i;
bool vis[100];
memset(vis, 0, sizeof(vis));
for(i = 0; i < 20; i++)
if(n >= a[i])
vis[getsg2(n - a[i])] = 1;
for(i = 0; i < 100; i++)
if(vis[i] == 0)
break;
return sg2
= i;
}

int getsg4(int n)
{//求sg
if(sg
!= -1)
return sg
;
int i;
bool vis[1000];
memset(vis, 0, sizeof(vis));
vis[getsg4(n - 1)] = 1;
for(i = 2; i <= 1010; i += 2)
{
if(n >= i)
vis[getsg4(n - i)] = 1;
else
break;
}
for(i = 0; i < 1000; i++)
if(!vis[i])
break;
return sg
= i;
}

int main (void)
{
int n, i;
//求第二堆和第四堆的sg值
memset(sg, -1, sizeof(sg));
memset(sg2, -1, sizeof(sg));
sg[0] = 0;
sg2[0] = 0;
for(i = 1; i < 1010; i++)
int ok = getsg4(i);
a[0] = 1;
a[1] = 2;
for(i = 2; i < 20 ; i++)
a[i] = a[i - 1] + a[i - 2];
for(i = 1; i < 1010; i++)
int ok = getsg2(i);

while(scanf("%d", &n) != EOF)
{
if(n == 0)
break;
int sum = 0, a;
for(i = 1; i <= n; i++)
{
scanf("%d", &a);
if(i == 1)
sum ^= (a % 3);
else if(i == 2)
sum ^= sg2[a];
else if(i == 3)
sum ^= a;
else if(i == 4)
sum ^= sg[a];
else if(i == 5)
sum ^= a % 2 == 0 ? 0 : 1;
else
sum ^= (a % (i + 1));
}
if(sum == 0)
printf("Hrdv\n");
else
printf("Yougth\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: