码迷,mamicode.com
首页 > 其他好文 > 详细

O(1)求解自然数异或和

时间:2020-06-21 09:33:48      阅读:85      评论:0      收藏:0      [点我收藏+]

标签:次数   display   mat   个数   简单的   math   code   floor   sum   

又是一个不眠之夜。

求:

\[f_i=1 \bigoplus 2 \bigoplus 3 \bigoplus...\bigoplus (i-1) \bigoplus i \]

\(O(logn)\)算法

考虑按位分析

对于\(f_i\)的第\(j\)位,它的值只与该位1出现次数有关。

而第\(j\)位1的出现又是呈周期性分布的。

我们考虑\(f_i=0 \bigoplus 1 \bigoplus 2 \bigoplus 3 \bigoplus...\bigoplus (i-1) \bigoplus i\)

注意这里多加了一个0。

那么,在上式的各数中,第1位的变化为01010101

而第2位为00110011

第3位为00001111

以此类推。

周期分析

所以我们可以发现,第\(j\)位的值的出现是连续的,且每连续一组的相同值的个数为\(2^{j-1}\),这恰好是第\(j\)位的位权!

而对于数字的总个数,我们可以用\(x=i+1\)来表示。

分析第\(j\)位的值\((j \ge 2)\)

则第\(j\)位的出现的整组共有\(t=\lfloor{{x}\over{2^{j-1}}}\rfloor\)个,其中奇数组为0,偶数组为1,且其中出现数字1的总个数必定为偶数。

\(t\)为奇数,说明剩余的不完整组的值为1,同时若\(x\)也为奇数,说明\(f_i\)的第\(j\)位为1;否则\(f_i\)的第\(j\)位为0。

由此,我们可以得到第\(j\)位的值\((j \ge 2)\)

对于第1位,它出现的组共有\(x\)个,其中值为1的有\(\lfloor{{x}\over{2}}\rfloor\)个,故\(f_i\)的第1位等于\(x\)的第2位。

综上可以在\(O(logn)\)时间复杂度内求解。

\(O(1)\)算法

其实就是对\(O(logn)\)的算法作了一个小的总结。

分析第\(j\)位的值\((j \ge 2)\)

我们知道,当且仅当\(t = \lfloor{{x}\over{2^{j-1}}}\rfloor\)为奇数,同时\(x\)也为奇数时,第\(j\)位才为1;否则第\(j\)位为0。

体现在\(x\)这个数本身上,就是当\(x\)第1位为1时,\(f_i\)的第2位及以上与\(x\)的相同。

而当\(x\)第1位为0时,\(f_i\)的第2位及以上都为0。

然后第1位的特判很好处理,就是\(f_i\)的第1位等于\(x\)的第2位。

由此可以在\(O(1)\)时间复杂度内求解。

upd:代码实现

闲来无事写个代码(因为太菜所以不会更简单的写法

int xorsum(int x)
{
	++x;
	return ( (x&1) ? (x&(INT_MAX-1)) : 0 ) | ( (x&2) ? 1 : 0 );
}

O(1)求解自然数异或和

标签:次数   display   mat   个数   简单的   math   code   floor   sum   

原文地址:https://www.cnblogs.com/-SingerCoder/p/13171117.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!