现在的位置: 首页 > 综合 > 正文

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

2014年09月29日 综合 ⁄ 共 3232字 ⁄ 字号 评论关闭

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[n] != -1)
		return sg[n];
	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[n] = 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[n] != -1)
		return sg[n];
	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[n] = 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[n] != -1)
		return sg2[n];
	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[n] = i;
}


int getsg4(int n)
{//求sg 
	if(sg[n] != -1)
		return sg[n];
	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[n] = 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;
}

抱歉!评论已关闭.