题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=4588
思路:
0 0000
1 0001
2 0010
3 0011
4 0100
5 0101
6 0110
7 0111
8 1000
9 1001
10 1010
观察可知,第i位有(1<<i)个0,与(1<<i)个1,按照长度为(1<<(i+1))长度循环。则对于数n,可以求出1到n中各位1的个数num2[i],则进位次数为sum(num[i] / 2),注意每次向高位进位(num2[i+1]+=num2[i] / 2)。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long LL; LL num1[65],num2[65]; void solve(LL num[],LL n) { for(int i=0;i<63;i++) num[i]=0; n++; for(int i=0;i<63;i++) { LL tmp1=(1LL)<<(i+1); LL tmp2=(1LL)<<i; num[i]+=n/tmp1*(1<<i); if(n%tmp1>tmp2)num[i]+=n%tmp1-tmp2; } /*for(int i=0;i<63;i++) cout<<i<<" "<<num[i]<<endl;*/ } int main() { LL a,b; //solve(num1,20); //solve(num2,6); while(scanf("%I64d%I64d",&a,&b)==2) { solve(num1,a-1); solve(num2,b); for(int i=0;i<63;i++) num2[i]-=num1[i]; LL ans=0; for(int i=0;i<63;i++) { ans+=num2[i]/2; num2[i+1]+=num2[i]/2; } printf("%I64d\n",ans); } return 0; }
时间: 2024-12-27 09:22:30