POJ 3252 Round Numbers(组合数学)

题目链接

SB了。。。20亿,我居然用了int,本来觉得这个组合情况比较多,很难写,费了好大劲错了几遍之后。。自己都觉得没错了。。还是WA,找AC代码对拍,1000以下的数据都没问题。。我仔细一看题,这是2后边9个0。。。

题意:求start - end之间多少个二进制时0的个数>=1的个数。

思路:求出1-key的数,相减即可。假如key二进制有len位,那么1到len-1的数都符合。特殊讨论len位的时候的情况。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <string>
 4 using namespace std;
 5 long long ba[40];
 6 long long c[40][40];
 7 long long judge(long long key)
 8 {
 9     int ans = 0,i,j,k,t1,t2;
10     if(key == 1||key == 0) return 0;
11     for(i = 1;i <= 31;i ++)
12     {
13         if(ba[i+1] > key)
14         {
15             t1 = 1,t2 = 0;
16             for(j = i-1;j >= 0;j --)//特殊讨论
17             {
18                 if(ba[j]&key)
19                 {
20                     t2 ++;
21                     for(k = 0;k <= i+1-t1-t2;k ++)
22                     {
23                         if(k + t2 >= (i+1-k-t2))
24                         ans += c[i+1-t1-t2][k];
25                     }
26                     t2 --;
27                     t1 ++;
28                 }
29                 else
30                 t2 ++;
31             }
32             if(t2 >= t1)
33             ans ++;
34             break;
35         }
36         for(j = 0;j <= i;j ++)//第一位是1,还有i位。从i位中选j个0
37         {
38             if(2*j >= i+1)
39             ans += c[i][j];
40         }
41     }
42     return ans;
43 }
44 int main()
45 {
46     int i,j;
47     long long start,end;
48     for(i = 0;i <= 31;i ++)
49     c[i][0] = 1;
50     for(i = 1;i <= 31;i ++)
51     {
52         for(j = 1;j <= 31;j ++)
53         c[i][j] = c[i-1][j-1] + c[i-1][j];
54     }
55     ba[0] = 1;
56     for(i = 1;i <= 31;i ++)
57     ba[i] = 2*ba[i-1];
58     scanf("%lld%lld",&start,&end);
59     printf("%d\n",judge(end) - judge(start-1));
60     return 0;
61 }

 

 

posted @ 2013-01-23 10:51  Naix_x  阅读(155)  评论(0编辑  收藏  举报