题意: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;
}