簡單的組合數學。ios
題意:給出兩個數,找出這兩個數之間的Round Numbers。範圍包括這兩個數。ide
所謂的Round Numbers就是將給出的十進制數轉化成二進制以後,0的個數 >= 1的個數。spa
思路:code
設給出的數爲m,其二進制長度爲len。blog
先找出長度小於 len 的狀況,這一種狀況比較簡單。ci
另外一種就是尋找和 m 的長度相同且 <= m的狀況。數學
從高位到地位枚舉m的爲1的位置,設爲site。string
計算site以前的0和1 的個數差 記爲 lead,而後計算出site以後最少能夠有幾個0,剩下的就是組合數的累加了。it
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 6 #define LL unsigned long long 7 #define Max(a,b) (a > b ? a : b) 8 9 using namespace std; 10 11 LL bin[60],cn[50][50]; 12 13 LL cal(LL m) 14 { 15 16 int i,j,len,lead; 17 18 i = 1; 19 20 while(m > 0) 21 { 22 bin[i++] = m%2; 23 m /= 2; 24 } 25 26 len = i-1; 27 28 LL ans = 0; 29 30 for(i = 1;i < len; ++i)//統計比m短的狀況 31 { 32 for(j = (i+1)/2;j < i; ++j)//j表明0的個數 33 { 34 ans += cn[j][i-1]; 35 } 36 } 37 38 for(lead = 1,i = len-1;i >= 1;i--)//lead統計 sum(1) - sum(0) 39 { 40 if(bin[i] == 1) 41 { 42 for(j = Max(0,(i + lead - 1)/2);j < i; ++j)//j表明0的個數 43 { 44 ans += cn[j][i-1]; 45 } 46 ++lead; 47 } 48 else 49 { 50 --lead; 51 } 52 } 53 54 if(lead <= 0 && bin[1]) 55 ans += 2; 56 else if(lead <= 0) 57 ++ans; 58 else if(lead == 1 && bin[1] && len != 1) 59 ans += 1; 60 61 return ans; 62 } 63 64 void init()//c(n,m) = c(n-1,m-1) + c(n,m-1); 從m中選n 65 { 66 int i,j; 67 cn[0][0] = 0; 68 for(i = 1;i <= 32; ++i) 69 { 70 for(j = 0;j <= i; j++) 71 { 72 if(j == 1) 73 cn[j][i] = i; 74 else if(j == 0 || i == j) 75 cn[j][i] = 1; 76 else 77 cn[j][i] = cn[j-1][i-1] + cn[j][i-1]; 78 } 79 } 80 } 81 82 int main() 83 { 84 85 LL l,r; 86 87 init(); 88 89 while(cin>>l>>r) 90 { 91 92 l = cal(l-1); 93 94 r = cal(r); 95 96 cout<<r-l<<endl; 97 } 98 return 0; 99 }