NOJ [1314] Brave Sword [1416] Clear Up

这两题换汤不换药

都是相当于求出在数组里只出现一次的数

其实有很多方法,例如哈希,位运算

我用的是位运算的异或运算


a.先把所有数异或一遍,因为其他数相同,异或值为0,那么最后的异或值就是那两个只出现一次的数的异或值。

b.得到那个异或值以后,分析,既然这两个数不一样,那么异或以后必不为0,换句话说,在那个值对应的二进制数的某一位,一定是1。

c.这样的话,那一位上两个数一定不一样例如1110,1010,第二位不一样,异或后那一位才会为1.

d,这样我们就得到了划分的标准,接下来,把数组分成2份,分别是1.那一位上为1的、2.那一位上是0的

e.然后分别进行异或运算,得到的异或值就是那两个数


#include<stdio.h>

int allnum[1000000];
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		int i,j,s=0;
		for(i=0;i<n;i++)
		{
			scanf("%d",&allnum[i]);
			s^=allnum[i];
		}
		int first;
		//寻找xor第一位为1的位置
		for(i=0;i<32;i++)
		{
			if((s>>i)%2==1)
			{
				first=i;
				break;
			}
		}
		int one=0,another=0;
		for(i=0;i<n;i++)
		{
			if((allnum[i]>>first)%2==1)
			   one^=allnum[i];
            else
               another^=allnum[i];
		}
		printf("%d %d\n",one<another?one:another,one>another?one:another);
	} 
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值