Gray码数组中是否存在4个元素的异或结果为0?

问题:给定一个数组,该数组中的相邻的两个元素其二进制代码只在某个位上不同(类似于gray码),问能否在该数组中找到四个数,这四个数的异或的值是0。
限制:数组中的每个元素的取值范围是[0,2^64),数组的个数n的取值范围是[4,100000]
来源:CodeChef   http://www.codechef.com/JULY12/problems/GRAYSC

关键字:抽屉原理/鸽笼原理

分析
定义1 具有上述性质的数组我们称为A数组

性质1 A数组的相邻的元素异或之后的值只有一个bit为1。
性质2 如果存在i,使得B[i] = B[i+1],那么A[i] = A[i+2]。


定义2 计算A数组中任意两个相邻的数的异或的值,可以导出一个新的数组,该数组称为B数组。

定义3 计算A数组(0-index)中任意偶数index的元素与其后一个元素的异或的值,可以导出一个新的数组,该数组称为C数组。显然C数组是B的一个子数组。

性质3 如果A数组有n个元素,则B数组有n-1个元素,C数组有n/2个元素。
性质4 如果存在着i + 1 < j,使得B[i] == B[j],则(i,i+1,j,j+1)是一组解。对于C数组亦然。
性质5 B数组中的每个元素的二进制表示中只有一个bit是1。对于C数组亦然。

引理1 当n >= 130时,A数组必定有4个不同的元素,使得其异或的结果为0。

因为当n >= 130时,此时C数组的元素个数至少有65个。由于C数组元素的二进制表示只有一个bit是1,因此最多有64个不同的C元素。根据抽屉原理,即C数组中至少有两个数相同。 再根据性质4,必然有解。

引理2 当n >= 68时,A数组必定有4个不同的元素,使得其异或的结果为0。

因为n >= 68,所以B数组的元素个数至少有n-1 >= 67个,由于B数组元素的二进制表示只有一个bit是1,因此最多有64个不同的B元素,因此以下三种情况必居其一
(1)存在着i < j < k < p,使得B[i] == B[j] == B[k] == B[p],此时i + 1 <= j < k,根据性质4有解
(2)存在着i< j < k,p < q,使得B[i] == B[j] == B[k],B[p] == B[q],此时i + 1 <= j < k,根据性质4有解
(3)存在着i < j,p < q,u < v(i < p < u),使得B[i] == B[j],B[p] == B[q],B[u] == B[v]
(3.1)如果i + 1 < j 或 p + 1 < q 或 u + 1 < v,则根据性质4有解
(3.2)如果i + 1 == j且p + 1 == q且u + 1 == v 且i + 1 == p,则(i,i+2,p,p+2)是一组解
(3.3)如果i + 1 == j且p + 1 == q且u + 1 == v 且i + 2 < p,则(i,i+2,p,p+2)是一组解
(3.4)如果i + 1 == j且p + 1 == q且u + 1 == v 且p + 1 == u,则(p,p+2,u,u+2)是一组解
(3.5)如果i + 1 == j且p + 1 == q且u + 1 == v 且p + 2 < u,则(p,p+2,u,u+2)是一组解
(3.6)如果i + 1 == j且p + 1 == q且u + 1 == v 且i + 2 == p 且 p + 2 == u,则(i,i+2=p,p+2=u,u+2)是一组解
即当n >= 68时必定有解


方案一:n^4算法。

	for(unsigned int i = 0;i < n;++i)
	{
		for(unsigned int k = i + 1;k < n;++k)
		{
			for(unsigned int p = k + 1;p < n;++p)
			{
				for(unsigned int q = p + 1;q < n;++q)
				{
					if(0 == (A[i]^A[k]^A[p]^A[q])) return true;
				}
			}
		}
	}
	return false;

方案二:n^3*logn算法。

	std::sort(A.begin(),A.end());
	for(unsigned int i = 0;i < n;++i)
	{
		for(unsigned int k = i + 1;k < n;++k)
		{
			for(unsigned int p = k + 1;p < n;++p)
			{
				unsigned long long x = A[i]^A[k]^A[p];
				if(std::binary_search(A.begin()+p+1,A.end(),x)) return true;
			}
		}
	}
	return false;

方案三:n^2或者n^2*logn算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值