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 }

 

 

你可能感兴趣的:(number)