Count The Carries
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 1538 Accepted Submission(s): 540
思路:把這些數字的二進制縱向羅列出來,然後一位一位的把和加起來,最終得到總的進位數。從1到x,第i位上1的總數是x左移i+1位再右移i位後得到的(在第0位上,1和0以1010101010的週期出現,並且每個週期一個1,在第1位上,1和0以11001100的週期出現,並且每個週期2個1,以此類推,則第n位上的1的個數是x/2^n*2^(n-1),即先左移n+1位,再右移n位),在這裏就卡了很久。。。如果x在i位上面上是1,特殊判斷一下,求一下週期以外的1的個數,這個時候的1的個數是a%(1<<k)+1。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
ll val(ll a,int k)
{
if(a == -1) return 0;
ll t = ((a>>(k+1))<<k);
if(a&(1ll<<k)) t+=a%(1ll<<k)+1;
return t;
}
int main()
{
ll ans,carry;
int x,y;
while(scanf("%d%d",&x,&y)!=EOF)
{
ans = 0;
carry = 0;
for(int i = 0;i < 63;i++)
{
carry += val(y,i) - val(x-1,i);
carry /= 2;
ans += carry;
}
printf("%I64d\n",ans);
}
return 0;
}