hdu 2176 取(m堆)石子游戏(博弈,异或运算)

题意:http://acm.hdu.edu.cn/showproblem.php?pid=2176

这也就是nim game(异或理论)。但是要求出“先取者第1次取子的所有方法. 如果从有a个石子的堆中取若干个后剩下b个后会胜就输出a b”。

必须对异或运算有一定认识:

#include<iostream>
#include<bitset> 
using namespace std;
void binary(int n){
   int i;
   if (n){
      i = n%2;
      binary(n/2);
      cout<<i;
   }
}
int main(){  
    int c=17^0;  // 任何数和0异或结果是他本身 
    bitset<8> bitc(c);  // bitset也能输出二进制,但是要定义多个相关变量。 
    cout<<bitc<<endl;   
    int a=30,b=45;   //用异或实现不用中间值的两值交换。 
    cout<<a<<"=";   binary(a);  cout<<endl; 
    cout<<b<<"=";   binary(b);  cout<<endl;
    a=a^b;  //a变成新的异或量 
    binary(a);  cout<<endl;
    b=b^a;  //b--异或量-->a 
    binary(b);  cout<<endl;
    a=a^b;  //异或量--a-->b 
    binary(a);   cout<<endl;//由此证明异或操作是可逆的,a^b=c,b^c=a,c^a=b. a,b,c相互转化。 
    cout<<a<<"=";   binary(a);  cout<<endl; 
    cout<<b<<"=";   binary(b);  cout<<endl;
	return 0;
}
有了上述基础后就可以解决它了:

#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=2e5+5;
int a[maxn];
int main()
{
    int m,i;
    while(~scanf("%d",&m)&&m)
    {
        int sum=0,b;
        for(i=0;i<m;i++)  {
            scanf("%d",&a[i]);
            sum=sum^a[i];
        }
        if(sum==0) printf("No\n");  //sum 最终的结果:非平衡的2进制表示值。若是0则平衡。
        else
        {
            printf("Yes\n");
            for(i=0;i<m;i++){
                b=sum^a[i];  //等于对一个a[i]做“减法”,试图让所有堆达到平衡态
                if(b<a[i])
                    printf("%d %d\n",a[i],b);
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值