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 }