题目大意:给出x - y,问x一直加到y,二进制的加法,总共进了多少次位。
解题思路:这题需要想到从x加到y,这里的二进制数的每一位有周期性的变化,例如:从1 - 3(十进制)(00,01,10,11),这里的最后一位就是0、1、0、1。而第二位是0、0、1、1。可以发现最后一位是以两个为一周期,往前一位是以4个为一周期,这样第i位(从后数)就是以2^i为一周期。
然后每个位上的1只要有两个就进一次位,这样就需要把每一位上的1都统计出来。因为周期是从0开始的,所以如果要算x到y之间有多少的1,就需要分别统计0 - y 之间的1,然后减去0- (x- 1) 之间的1.
然后再做进位的计算。从低位开始没两个1进一次位,然后进的1的总数要加到高一位的那个1的总数中,要注意:这里可能会有每个位都统计了进位的次数,但是不要忘了最高的那一位如果向前一位进位的次数大于2的话就说明还有进位发生,所以所有的次数还需加上这个数/2.
代码:
#include <stdio.h> #include <string.h> #include <iostream> using namespace std; const int N = 35; long long x, y; typedef long long ll; ll s1[N], s2[N], t[N]; void handle (ll y, ll * s) { for (int i = 0; i <= 32; i++) { s[i] = y / t[ i + 1] * t[i]; ll d = y % t[i + 1] - t[i]; s[i] += d > 0 ? d: 0; } } ll solve () { ll ans = 0; ll a = 0; for (int i = 0; i < 32; i++) { a = ( s1[i] - s2[i] + a ) / 2; ans += a; } while (a) { ans += a / 2; a = a / 2; } return ans; } int main () { t[0] = 1; for (int i = 1; i < N; i++) t[i] = 2 * t[i - 1]; while (cin>>x>>y) { memset (s1, 0, sizeof (s1)); memset (s2, 0, sizeof (s2)); handle (y + 1, s1); handle (x, s2); cout<<solve()<<endl; } return 0; }
poj 4588 Count The Carries(数论),布布扣,bubuko.com
poj 4588 Count The Carries(数论)
原文:http://blog.csdn.net/u012997373/article/details/23940649