原题是 : TopCoder SRM 416 DIV 2 Same binary weight
先看看这几个例子:
1717(0110 1011 0101),下一位是 1718(0110 1011 0110)
767(0010 1111 1111),下一位是 895(0011 0111 1111)
348(0001 0101 1100),下一位是 355(0001 0110 0011)
其中不难发现一个规律,从右起的第一个“01”改变为“10”,并且在“01”的后面所有的“1”都移动至最后,事实上,这个就是解题的关键点,那么整个问题求解的核心就转移到这两个子问题:
1. 将右起第一个“01”,改变为“10”
2. 将该“01”后面的所有“1”移动至最后
位运算的解法
1. 约定 x 是输入的 N,如 x = 1717,则 -x = -1717,二进制中 -x = -1717(1001 0100 1011 原码取反加一)
2. 令 b = x & (-x),得到 x 中最后一个 “1” 的位置
3. 令 t = x + b, 产生进位,实现 “01” 改变为 “10”
4. 令 s = t ^ x, 得到进位过程中发生变动的位
5. (s >> 2),“10” -》 "10" 后这两位就不要再去改变它们了,所以右移 2 位(去掉这两位)
6. 令 k = (s >> 2)/ b,除去“01” -》 “10”这两位外,将“01”以后至最后一个“1“(包含最后一个”1“)之间的所有”1“移动至最后,原理见下
7. 那么最后的结果就是 t | k
汇编中的除法原理:
二进制的除法本质是通过重复减法运算实现
即通过重复”从被除数的高位依次取出每一位, 被取出的数据加上上次的减法结果*2,
然后减去除数”的处理, 求出除法结果
那么如此一来,“01”以后至最后一个“1“(包含最后一个”1“)之间的所有”1“移动至最后,代码就不贴了,自己写