hdu2176取(m堆)石子游戏

取(m堆)石子游戏

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1971    Accepted Submission(s): 1142

Problem Description

m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次取时可以从有8个的那一堆取走7个剩下1个,也可以从有9个的中那一堆取走9个剩下0个,也可以从有10个的中那一堆取走7个剩下3个.

Input

输入有多组.每组第1行是m,m<=200000. 后面m个非零正整数.m=0退出.

Output

先取者负输出No.先取者胜输出Yes,然后输出先取者第1次取子的所有方法.如果从有a个石子的堆中取若干个后剩下b个后会胜就输出a b.参看Sample Output.

Sample Input

2
45 45
3
3 6 9
5
5 7 8 9 10
0

Sample Output

No
Yes
9 5
Yes
8 1
9 0
10 3

题目类型:博弈之尼姆博弈

题意:中文题意,不解释了,只是如果是Yes的时候要注意输出顺序就行了

题解:根据尼姆博弈,先设置变量m=0(初值),一直与a[i]求异或,结束后如果为0则输出no,否则输出yes,并且

把怎么到达该点的方法列出来,怎么将尼姆博弈中的非奇异点转换成奇异点,我刚开始用的是两重循环,交上去后发

现超时了,也难怪,数据那么大。。。。正确的方法是用得到的m与当前的a[i]求异或,得到的答案就是去除掉当前a

[i]后剩下的所有点的异或(为什么?因为两个相等的值异或为0异或一次再异或一次即没有异或该点),如果该值比a

[i]小,说明可以从a[i]中去除一部分得到该值,两个相等的值异或便得到0,即可。

附上详细代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
int a[200001];
int main()
{
	int i,j,n,m,k;
	while(~scanf("%d",&n)&&n)
	{
		for(i=0;i<n;i++)
			scanf("%d",&a[i]);
		m=a[0];
		for(i=1;i<n;i++)
		{
			m=m^a[i];
		}
		if(m==0)
			printf("No\n");
		else
		{
			printf("Yes\n");
			for(i=0;i<n;i++)
			{
				k=m^a[i];		//将异或得到的答案跟其中a[i]再异或一次就相当于把a[i]去除后
								//剩下的所有的异或得到的值,如果该值比a[i]小说明可以从a[i]
								//中去除一部分得到该值,两个相等的值异或便得到0,即可
				if(k<a[i])
					printf("%d %d\n",a[i],k);
			}

		}
	}
	return 0;
}
时间: 2024-11-03 15:16:54

hdu2176取(m堆)石子游戏的相关文章

hdu2176 取(m堆)石子游戏(nim博弈)

取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2713    Accepted Submission(s): 1617 Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次

ACM-尼姆博弈之取(m堆)石子游戏——hdu2176

取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1486    Accepted Submission(s): 865 Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次取

HDU 2176 取(m堆)石子游戏 博弈

取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3598    Accepted Submission(s): 2151 Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次取

取(2堆)石子游戏(威佐夫博弈+hdu2177)

T - 取(2堆)石子游戏 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 2177 Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后把石子全部取完者为胜者.现在给出初始的两堆石子的数目,

HDU 2176 取(m堆)石子游戏 (Nim博弈)

取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1937    Accepted Submission(s): 1115 Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次取

杭电 2176 取(m堆)石子游戏(博弈)

取(m堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1741    Accepted Submission(s): 1014 Problem Description m堆石子,两人轮流取.只能在1堆中取.取完者胜.先取者负输出No.先取者胜输出Yes,然后输出怎样取子.例如5堆 5,7,8,9,10先取者胜,先取者第1次

hdu 2177 取(2堆)石子游戏

天资愚笨啊,网上的一大堆没看懂...... 总结百科的方法为: 1.a==b 同时减去a 得到0,0 2.a==a_k      b>b_k b -(b-b_k) 3.a==a_k     b<b_k 同时拿走a_k-a_(b-a_k) 得到 a_(b-a_k)    a_(b-a_k) + b-a_k 4.a>a_k       b==b_k 从a中拿走 a-a_k 5.a<a_k       b==b_k 5.1 a==a_ j   (j<k) b-(b-b_ j) 得到

ACM-威佐夫博弈之取(2堆)石子游戏——hdu2177

取(2堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 932    Accepted Submission(s): 557 Problem Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同

hdu2177 取(2堆)石子游戏 (威佐夫博弈)

取(2堆)石子游戏 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2054    Accepted Submission(s): 1238 Problem Description 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走