思路:容易发现二进制表示的数的最低位规律是01010101……;接着是001100110011……;接着是:0000111100001111……
这样我们发现每一位的循环节是2^(i+1),前2^i是0,后面的是1.这样就可以算出每一位1出现的次数。
代码如下:
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define ll __int64 6 using namespace std; 7 ll a[35]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384, 8 32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608, 9 16777216,33554432,67108864,134217728,268435456,536870912,1073741824, 10 2147483648,4294967296,8589934592,17179869184}; 11 ll sa[35],sb[35],s[100]; 12 int get(int n) 13 { 14 int bit=0; 15 while(n){ 16 bit++; 17 n>>=1; 18 } 19 return bit; 20 } 21 void solve(int n,ll *aa) 22 { 23 ll i,j,nn=n+1; 24 if(n<=0) return; 25 int len=get(n); 26 for(int k=0;k<len;k++){ 27 aa[k]+=nn/a[k+1]*a[k]; 28 j=nn%a[k+1]; 29 if(j>=a[k]) j-=a[k]; 30 else j=0; 31 aa[k]+=j; 32 } 33 } 34 int main() 35 { 36 int n,m,len1,len2; 37 ll c; 38 while(scanf("%d%d",&n,&m)!=EOF){ 39 memset(sa,0,sizeof(sa)); 40 memset(sb,0,sizeof(sb)); 41 memset(s,0,sizeof(s)); 42 solve(m,sa); 43 solve(n-1,sb); 44 for(int i=0;i<35;i++) s[i]=sa[i]-sb[i]; 45 ll ans=0; 46 for(int i=0;i<100;i++){ 47 c=(s[i]>>1); 48 ans+=c; 49 s[i+1]+=c; 50 } 51 printf("%I64d\n",ans); 52 } 53 return 0; 54 }