首先想到打表.....
2x10^9坑定是不行的.....我隔壁是血淋淋的教训——3.6G
于是我想到了按位数来分0 1的个数。但最后推出来2*10^9都才30000多,绝对是错了。后来才知道应该排列组合。
只不过这次找到一个10转2的函数itoa(num,char,2) 如果想用整形数,用atoi(itoa(num,char,2))。
之后判断1的个数,最朴素的是扫一遍。
这里有种与n无关,只与1的个数有关的判断法

1 int BitCount2(unsigned int n) 2 { 3 unsigned int c =0 ; 4 for (c =0; n; ++c) 5 { 6 n &= (n -1) ; // 清除最低位的1 7 } 8 return c ; 9 }
但正解其实并非如此......将一定位数的方数用组合数做出来后,再按位进行加减

1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 5 using namespace std; 6 7 int a[40] ; 8 int c[40][40] ; 9 10 void prework() 11 { 12 memset(c,0,sizeof(c)); 13 c[0][0] = 1 ; 14 c[1][0] = c[1][1] = 1 ; 15 for (int i=2;i<40;i++) 16 { 17 c[i][i] = c[i][0] = 1; 18 for (int j=1;j<i;j++) 19 c[i][j]=c[i-1][j]+c[i-1][j-1] ; 20 } 21 } 22 23 int work(int x) 24 { 25 if (x==0) return 0; 26 int cn=0,ret=0; 27 while (x) a[cn++]=x&1 , x>>=1 ; 28 for (int pos=0;pos<cn-1;pos++) 29 for (int z=pos;z>=0&&z>=pos-z+1;z--) 30 ret+=c[pos][z] ; 31 int now_one=1; 32 for (int i=cn-2;i>=0;i--) 33 { 34 if (a[i]==1) 35 { 36 int now_zero=cn-i-now_one ; 37 for (int j=i;j>=0&&now_zero+j>=now_one+i-j;j--) 38 ret+=c[i][j] ; 39 now_one++ ; 40 } 41 } 42 if (cn-now_one>=now_one)ret++ ; 43 return ret ; 44 } 45 int l,r; 46 int main() 47 { 48 // freopen("testA.in","r",stdin); 49 // freopen("testA.out","w",stdout); 50 prework() ; 51 scanf("%d%d",&l,&r); 52 printf("%d",work(r)-work(l-1)); 53 return 0 ; 54 }