POJ 3252 Round Numbers
简单的组合数学。
题意:给出两个数,找出这两个数之间的Round Numbers。范围包括这两个数。
所谓的Round Numbers就是将给出的十进制数转化成二进制之后,0的个数 >= 1的个数。
思路:
设给出的数为m,其二进制长度为len。
先找出长度小于 len 的情况,这一种情况比较简单。
另一种就是寻找和 m 的长度相同且 <= m的情况。
从高位到地位枚举m的为1的位置,设为site。
计算site之前的0和1 的个数差 记为 lead,然后计算出site之后最少可以有几个0,剩下的就是组合数的累加了。
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 }