http://poj.org/problem?id=3252
//自己搞了很长时间。。。现在刚刚有点明白。。
1 #include <iostream>
2
3 using namespace std;
4 long long c[35][35];
5 void init(){
6 for(int i=0;i<33;i++){//初始化组合数利用的是公式
7 c[i][0] = c[i][i] = 1;
8 for(int j=1;j<i;j++)
9 c[i][j] = c[i-1][j]+c[i-1][j-1];//公式
10 }
11 }
12 int mx(int a,int b){
13 if(a>b)
14 return a;
15 return b;
16 }
17 long long solve(long long n){
18 int len=0;
19 int bit[35];
20 while(n){//得到二进制数1--len
21 bit[++len] = n%2;
22 n = n/2;
23 }
24 long long sum = 0;
25 for(int i=1;i<len;i++){//当长度小于len时
26 for(int j=(i+1)/2;j<i;j++)
27 sum += c[i-1][j];
28 }
29 //长度等于len时
30 int one = 1;
31 int zero =0;
32 for(int i=len-1;i;i--){
33 if(bit[i]){//如果在这一位是1则将其其改为0,那么得到的数一定比原来的数小,再枚举。。
34 zero ++;//改为0后。。0的数目加1,一的数目不变
35 for(int j = mx(0,(len+1)/2-zero);j<i;j++)
36 sum += c[i-1][j];
37 zero--;//用完后改归来,0的数目-1,1的数目+1;
38 one++;
39 }
40 else //这一位是0, 那么就将0的数目加1
41 zero++;
42 }
43 return sum;
44 }
45 int main()
46 {
47 init();
48 long long a,b;
49 while(cin>>a>>b){ //[a,b]=[0,b+1)-[0,a),所以此处就应该应该这么写
50 cout<<solve(b+1)-solve(a)<<endl;
51 }
52 return 0;
53 }