就是统计每个数不算本身的round数,具体解法如下
前前后后做过三遍,每一次都wa了好多次.........
dp解法:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define MAX 40 using namespace std; typedef int LL; LL dp[MAX][MAX]; void pre ( ) { dp[1][0] = dp[0][1] = 1; for ( int i = 0 ; i <= 35 ; i++ ) for ( int j = 0 ; j <= 35 ; j++ ) if ( i == 0 || j == 0 ) dp[i][j] = 1; else dp[i][j] = dp[i][j-1] + dp[i-1][j]; } LL calc ( LL n ) { LL res = 0; int cnt = 1; int temp = 0; if ( n == 0 ) return 1; while ( n>>temp ) temp++; temp--; for ( int i = temp ; i > 0 ; i -- ) { if ((1<<(i-1))&n) { for ( int j = i-1; j+1>=cnt+i-1-j&&j>=0 ; j-- ) res += dp[j][i-1-j]; cnt++; } else cnt--; } for ( int i = temp-1 ; i >= 0 ; i-- ) { int temp; if ( i&1 ) temp = (i+1)/2; else temp = i/2+1; for ( int j = i ; j >= temp ; j-- ) res += dp[j][i-j]; } return res; } int main ( ) { LL n,m; pre(); while ( ~scanf ( "%d%d" , &n , &m ) ) { // cout <<"calc : 2 " << calc ( 2 ) << endl; // cout <<"calc: 12 " << calc ( 12 ) << endl; printf ( "%d\n" , calc (m+1) - calc ( n ) ); } }
#include <iostream> #include <cstdio> using namespace std; int c[40][40],b[40]; //注意啊,数组还是要取大些好啊,更大的空间总不会出错的,谨记// //此函数求排列组合C(n,m),即求从m件物品中取n件有多少中取法// void C() { int i,j; c[0][0]=1; for(i=1;i<40;i++) for(j=0;j<=i;j++) c[i][j]=(j==0)?c[i-1][j]:c[i-1][j]+c[i-1][j-1]; } //此函数求小于n的数中有多少round number// int round(int n) { int i=n,len=0,j,zero=0; int ans=0; while(i) { b[len++]=i%2; i>>=1; } //求n二进制// for(i=1;i<len-1;i++) //i+1(i+1<len)位数的二进制位数,第一位必为1,故不计入// { for(j=i/2+1;j<=i;j++) //j为其中0的位数// { ans+=c[i][j]; } } //运用排列组合知识,求从i位中取j位为零有多少种并累加// for(i=len-2;i>=0;i--) //计算位数为len的数中有多少小于n的round number,方法见上// { if(b[i]) { for(j=(len+1)/2-zero-1;j<=i;j++) { ans+=c[i][j]; } } else zero++; //zero记录在搜索过程中,已发现的0的个数// } return ans; } int main() { int a,b; scanf("%d%d",&a,&b); C(); printf("%d\n",round(b+1)-round(a));//此处亦有讲究,由于我们的round()所得为小于n的round number的个数,所以b+1,// return 0; //此时若b为round number,亦正确// }
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> using namespace std; int a ,b ; int s1[40], s2[40]; int cnt1 = 0 , cnt2 = 0 ; long long C ( long long index , long long bottom ) { if ( index > bottom / 2 ) index = bottom - index ; long long sum1 = 1 , sum2 = 1 ; for ( long long i = 0 ; i < index ; i ++ ) sum1 *= (long long) ( bottom - i ); for ( long long i = 1 ; i <= index ; i ++ ) sum2 *= ( long long )i; return sum1/sum2; } int c[40][40]; int ans = 0; void init ( ) { scanf ("%d%d" , &a , &b ); int zero = 0 , one = 0; while ( a ) { s1[++cnt1] = a%2; a /= 2; if ( s1[cnt1] ) one++; else zero++; } if ( zero >= one ) ans++; while ( b ) { s2[++cnt2] = b%2; b/= 2; } c[0][0] = 1; for ( int i = 1 ; i <= 35 ; i ++ ) for ( int j = 0 ; j <= i ; j ++ ) { c[j][i] = C ( j , i ); //cout << c[j][i] << endl; } } int solve ( ) { int zero = 0; int one = 1; int sum1 = 0; int sum2 = 0; for ( int i = cnt1-1 ; i > 0 ; i -- ) { if ( s1[i] == 1 ) { for ( int j = i-1 ; zero + 1 + j >= one + i -1 - j && j >=0 ; j -- ) sum1 += c[j][i-1]; one++; //if ( one - zero <= i -1 ) sum1++; //cout <<i << " "<< sum1 << endl; } else zero++; } // cout <<sum1 <<endl; if ( zero >= one ) sum1++; // if ( one != 2 && s1[1] == 1 && zero + 1 >= one - 1 ) sum1--; // cout << sum1 <<endl; for ( int i = cnt1 -2 ; i >= 0 ; i-- ) { int temp; if ( i &1 ) temp = ( i +1 )/2; else temp = i /2 + 1; for ( int j = i ; j >= temp ; j -- ) sum1 += c[j][i]; } // cout << sum1 << endl; zero = 0 , one = 1; for ( int i = cnt2-1 ; i > 0 ; i -- ) { if ( s2[i] == 1 ) { for ( int j = i-1 ; zero + 1 + j >= one + i -1 - j && j >= 0 ; j -- ) sum2 += c[j][i-1]; one++; // if ( one - zero <= i -1 ) sum2++; } else zero++; } if (zero >=one ) sum2++; // if ( one == 1 ) sum2++; for ( int i = cnt2 - 2 ; i >= 0 ; i -- ) { int temp; if ( i&1 ) temp = (i+1)/2; else temp = i/2+1; for ( int j = i ; j >= temp ; j -- ) sum2 += c[j][i]; } //cout << sum2 << endl; return sum2 - sum1 + ans ; } int main ( ) { init ( ); cout << solve ( ) << endl; }