求1到n这n个整数间的异或值 (O(1)算法)

问题:求1nn个整数间的异或值,即 1 xor 2 xor 3 ... xor n

记 f(x, y) 为x到y的所有整数的异或值。

对 f(2^k, 2^(k+1) -1) (注意文章中的 ^ 表示的是“幂”,xor 表示“异或”,or 表示“或”):

2^k 到 2^(k+1) -1 这2^k个数,最高位(+k位)的1个数为2^k,

若 k >= 1,则2^k为偶数,将这2^k个数的最高位(+k位)去掉,异或值不变。

因而 f(2^k, 2^(k+1) -1) = f(2^k - 2^k, 2^(k+1) -1 -2^k) = f(0, 2^k -1)

因而 f(0, 2^(k+1) -1) = f(0, 2^k -1) xor f(2^k, 2^(k+1) -1) = 0 (k >= 1)

即 f(0, 2^k - 1) = 0 (k >= 2)

对 f(0, n)  (n >= 4) 设n的最高位1是在+k位(k >= 2),

f(0, n) = f(0, 2^k - 1) xor f(2^k, n) = f(2^k, n)

对2^k到n这n+1-2^k个数,最高位(+k位)共有 m = n+1-2^k 个1,去除最高位的1

当n为奇数时,m是偶数,因而 f(0, n) = f(2^k, n) = f(0, n - 2^k)

由于n - 2^k 与 n同奇偶,递推上面的公式,可得:f(0, n) = f(0, n % 4)

当 n % 4 == 1 时, f(0, n) = f(0, 1) = 1

当 n % 4 == 3 时, f(0, n) = f(0, 3) = 0

当n为偶数时,m是奇数,因而 f(0, n) = f(2^k, n) = f(0, n - 2^k)  or  2^k

也就是说,最高位1保持不变,由于n - 2^k 与 n同奇偶,递推上面的公式,

可得:f(0, n) = nn or  f(0, n % 4)   (nn为 n的最低2位置0)

当 n % 4 == 0 时, f(0, n) = n

当 n % 4 == 2 时, f(0, n) = nn or  3 = n + 1 (公式对 n = 2仍成立)

综上所述:

f(1, n)  =  f(0, n)  =

n      n % 4 == 0

1      n % 4 == 1

n +1   n % 4 == 2

0      n % 4 == 3

代码:

unsigned xor_n(unsigned n)

{

unsigned t = n & 3;

if (& 1) return t / 2u ^ 1;

return t / 2u ^ n;

}

时间: 2024-10-25 14:24:26

求1到n这n个整数间的异或值 (O(1)算法)的相关文章

12_1求两个整数中的较小值,要求不能使用比较运算符, if-else, a>b?a:b, while for

转载请注明出处:http://www.cnblogs.com/wuzetiandaren/p/4253932.html  声明:现大部分文章为寻找问题时在网上相互转载,此博是为自己做个记录记录,方便自己也方便有类似问题的朋友,本文的思想也许有所借鉴,但源码均为本人实现,如有侵权,请发邮件表明文章和原出处地址,我一定在文章中注明.谢谢. 题目:求两个整数中的较小值,要求不能使用比较运算符, if-else, a>b?a:b, while for, 内嵌汇编递归第三方函数. 在网上看到一些网友给出了

输入两个整数,要求输出其中值较大者。要求用函数来找大数。

/* p176 例7.2 输入两个整数,要求输出其中值较大者.要求用函数来找大数. (1)函数名:应是见名知意,反应函数的功能,今定名为max (2)函数的类型:由于给定的两个数是整数,显然其中大者也是整数,也就是说max函数的值(即返回主调函数的值)应该是整型. (3)max函数的参数个数和类型:max函数应当有两个参数,以便从主函数接受两个整数,显然,参数的类型应当是整型. 在调用max函数时,应当给出两个整数作为实参,传给max函数中的两个形参*/ //编写程序: //(1)先编写max函

求两个用链表表示的整数的和

给定两个用链表表示的整数,每个结点包含一个数位.这些数位是反向存放的,也就是个位排在链表首部.编写函数对这两个整数求和,并用链表形式返回结果. 进阶       假设这些数位是正向存放的. LinkedListNode addLists(LinkedListNode l1, LinkedListNode l2, int carry) { /*两个链表全部都为空且进位为0,则函数返回*/ if (l1 == null &&l2 == null&&carry == 0) { r

位运算---整数间的转化

此题巧妙地转为熟悉的的求一个数中1的个数,告诉我们一些看似不熟悉的题目其实认真想想可以转为化我们熟悉的题目. //题目描述 // //编写一个函数,确定需要改变几个位,才能将整数A转变成整数B. //给定两个整数int A,int B.请返回需要改变的数位个数. //测试样例: //10, 5 //返回:4 //思路:A 需要变换 多少位 才能得到B,位变换无非就是0 - 1, 1 - 0的过程所以,A和B之间 有多少的不同的0 - 1, 1 - 0的变换就有需要多少位的变换, //由于异或操作

python中的整数、浮点数和布尔值

整数和浮点数有那个四则运算: 两种类型的数可以直接进行加减,当整数和浮点数进行加减的时候,结果会自动的变为浮点数,其中除法运算是“/”来表示的, 而余数的算术符号是“%”来表示的. 在布尔值的判断中我们拥有三种运算:与运算,非运算和或运算. 在Python中它把None,0和' '看成false,其他的数值和非字符串都看成true

表达式求值及转换算法

后缀表达式求值算法 stack operands;  //运算数栈 while(没到表达式尾) {     scanf("一个运算对象op");     if(op is 运算数)         operands.push(op);     else if(op is 运算符)     {         operand_right = operands.pop();         operand_left = operands.pop();         result = op

算法研究:一维多项式求值(秦九韶算法)

问题通式: 求指定点X处的函数值. 思路: 运用秦九韶算法 将多项式表述成如下嵌套模式: 于是可以转换成程序语言思想: 可通过for循环来实现. 代码实现: C语言代码如下: #include <stdio.h> /* *函数名:double odpf(double array[], int n, double x) *参数:double array[] 系数数组 * int n 表示n项 * double x x的值 *返回值:计算结果sum *说明:One dimensional poly

c语言用递归求:10的阶乘、100+99+98...+3+2+1的值。

#include <stdio.h> #include <string.h> void main(){ int myfun(int in); int a =myfun(10); printf("%d\n", a); } int myfun(int in){ if (in > 1) //将下面的*换成+,就可以求100+99+98...+3+2+1的值呢. return in * myfun(in-1); else return 1; } 原文地址:http

整数 浮点数 列表 字典 布尔值 格式化输出 输出

整数 print(21+34) 浮点数 print(2.2+2.6)print(8.4-4.2)列表 place_name = ["shen zhen", "shang hai","shan xi", ["xi an","wei nan","yan an"]]print(place_name[3][1])#结果print(wei nan) 输出 name=input("你的名字