码迷,mamicode.com
首页 > 其他好文 > 详细

POJ3252 组合数学

时间:2014-08-08 15:53:46      阅读:342      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   io   for   art   

POJ3252

问题重述:

求解在区间[start, finish]之间的Round Number的数目。所谓Round Number指的是,二进制表示中0的位数大于等于1的位数的整数。

分析:

1.假如能够分别得到[0, finish] 和 [0, start - 1]区间内的Round Number的数目n1, n2, 那么问题的答案就是n1 - n2. 因此问题可以转化为求解小于n的Round Number的数目。

2.假设整数N的二进制表示为 1,n2,n3,n4,..nk, 则可以把小于N的roundnumber的数目分为两个部分

  1)二进制表示位数小于k的Round Number的个数。

   容易知道位数为j的Round Number的个数为 C[j-1][0] + C[j - 1][1] + ... + C[j - 1][j / 2 - 1]。

  2)位数为k且小于N的Round Number的个数。

  M小于N可以理解为:M和N的二进制表示在出现第一个不同位之前的所有位都相同,且mj = 0, nj = 1,(j表示第一个不同位的序号)。因此小于N的Round Number的数目可以通过如下算法计算:找到N中非零位nj = 1, 令mj=0, 且m1 = n1, m2 = n2,.., mj-1   = nj-1,这样只需要令剩余的k - j位的非零位的数目使M满足Round Number的条件即可。

  例如对于N=1010010, 1)令M = 100xxxx, 那么M的后4位最多只能有2个1,因此满足该形式的M的个数有C[4][0] + C[4][1] + C[4][2]; 2)令M = 101000X, 则满足条件的M的个数为C[1][0] + C[1][1].

根据以上分析即可求解此问题。

AC代码

 1 //Memory: 232K        Time: 16MS
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 
 6 using namespace std;
 7 
 8 int c[64][64];
 9 int n[64];
10 
11 void init_c()
12 {
13     for (int i = 0; i < 64; i++) {
14         c[i][0] = 1;
15         c[i][i] = 1;
16     }
17     for (int i = 2; i < 64; i++)
18         for (int j = 1; j < i; j++)
19             c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
20 }
21 
22 int a[40];
23 int len = 0;
24 
25 int roundNum (long long n)
26 {
27     len = 0;
28     while(n) {
29         a[len++] = n % 2;
30         n /= 2;
31     }
32     int ret = 0;
33     
34     for (int i = 2; i < len; i++) {
35         for (int j = 0; j <= i / 2 - 1; j++) {
36             ret += c[i - 1][j];
37         }
38     }
39 
40     int cnt = 1;
41     for (int i = len - 2; i >= 0; i--) {
42         if (cnt > len / 2) break;
43         if ( a[i] ) {
44             for (int j = 0; j <= len / 2 - cnt; j++)
45                 ret += c[i][j];
46             cnt++;
47         }
48     }
49 
50     return ret;
51 }
52 
53 int main()
54 {
55     init_c();
56     long long s, f;
57     cin >> s >> f;
58     cout << roundNum(f + 1) - roundNum(s) << endl;
59     return 0;
60 }

 

POJ3252 组合数学,布布扣,bubuko.com

POJ3252 组合数学

标签:style   blog   http   color   os   io   for   art   

原文地址:http://www.cnblogs.com/junxie/p/3899352.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!