题意:有n个队伍比赛,比赛的规则是,如果人数是奇数,则任意两个队伍都要比直接决出冠军(n*(n-1)/2),如果人数是偶数的话,任意两个队比赛(n/2),给出你比赛次数,让你求n
解题思路:假设队伍大小为(2^p*x)则用枚举p 二分找x 就能得出答案,不过要注意数据范围!!
解题代码:
1 // File Name: 325b.c 2 // Author: darkdream 3 // Created Time: 2013年07月19日 星期五 16时44分33秒 4 5 #include<stdio.h> 6 #include<string.h> 7 #include<stdlib.h> 8 #include<time.h> 9 #include<math.h> 10 #include<ctype.h> 11 long long int up(long long int n) 12 { 13 double t = log(n)/log(2); 14 return int(t); 15 } 16 long long Pow(long long p) 17 { 18 long long sum = 1; 19 for(long long i = 1; i <= p ;i ++) 20 sum = sum * 2 ; 21 return sum ; 22 } 23 int cmp(const void *a , const void *b) 24 { 25 return *(long long *)a - *(long long *)b; 26 } 27 long long ans[100] = {0},pre =0 ; 28 int fen(long long n , long long p) 29 { 30 long long up = 0 ; 31 long long high; 32 if(p == 1) 33 { 34 high = n; 35 if(high >= 2 *1e9) 36 high = 2 * 1e9; 37 } 38 else 39 { 40 high = n/(p-1) + 1; 41 42 if(high >= 2*1e9) 43 high = 2*1e9; 44 } 45 long long mid = (up + high)/2; 46 //printf("%I64d** ",high); 47 while(up <= high) 48 { 49 mid = (up + high )/2; 50 if(mid*(mid-1)/2 + mid*(p-1) > n || mid*(mid-1)/2 +mid*(p-1) < 0 || mid*(mid-1)/2+mid*(p-1) < up*(up-1)/2 + up*(p-1) ) 51 high = mid-1; 52 else if(mid*(mid-1)/2 + mid*(p-1) < n) 53 up = mid + 1; 54 else 55 { 56 if(mid % 2 == 0 ) 57 break; 58 pre++; 59 ans[pre] = mid*p; 60 return 1; 61 } 62 } 63 return 0 ; 64 } 65 int main(){ 66 67 //freopen("/home/plac/problem/input.txt","r",stdin); 68 //freopen("/home/plac/problem/output.txt","w",stdout); 69 long long int n ; 70 scanf("%I64d",&n); 71 long long p = up(n) + 1; 72 int ok = 0 ; 73 for(long long i = 0 ;i <= p;i ++) 74 { 75 if(fen(n,Pow(i))) 76 ok = 1; 77 } 78 if(!ok) 79 printf("-1 "); 80 else 81 { 82 //qsort(ans+1,pre,sizeof(long long ),cmp); 83 for(int i = 1;i <= pre; i ++) 84 if(ans[i] != ans[i-1]) 85 printf("%I64d ",ans[i]); 86 } 87 return 0 ; 88 }