POJ 2886 Who Gets the Most Candies? 线段树
题目: http://poj.org/problem?id=2886
左右转的果断晕,题目不难,关键是准确的转啊转。因为题目要求输出约数个数最多的数,所以预处理[1,500000]的约数的个数就行了。还有利用反素数的做法,太专业了,还是暴力预处理吧。。。
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 5 const int MAXN = 500010; 6 7 struct Tree_Node 8 { 9 int left, right, sum; 10 Tree_Node(){} 11 Tree_Node(int left, int right, int sum) 12 { 13 this->left = left; 14 this->right = right; 15 this->sum = sum; 16 } 17 }tree[MAXN<<2]; 18 19 void build(int left, int right, int step) 20 { 21 tree[step] = Tree_Node(left, right, right-left+1); 22 if(tree[step].left == tree[step].right) 23 return; 24 int mid = left + (right-left) / 2; 25 build(left, mid, step<<1); 26 build(mid+1, right, step<<1|1); 27 } 28 29 int query(int num, int step) 30 { 31 tree[step].sum--; 32 if(tree[step].left == tree[step].right) 33 { 34 return tree[step].left; 35 } 36 if(num <= tree[step<<1].sum) 37 return query(num, step<<1); 38 else 39 return query(num - tree[step<<1].sum, step<<1|1); 40 } 41 42 int div[MAXN]; 43 void cnt_divisible() 44 { 45 int x = sqrt(MAXN); 46 for(int i = 1; i <= x; i++) 47 { 48 int y = MAXN / i; 49 for(int j = i+1; j <= y; j++) 50 div[i*j] += 2; 51 div[i*i]++; 52 } 53 } 54 55 char name[MAXN][11]; 56 int val[MAXN]; 57 int main() 58 { 59 cnt_divisible(); 60 int n, k; 61 while(scanf("%d %d", &n, &k) != EOF) 62 { 63 build(1, n, 1); 64 for(int i = 1; i <= n; i++) 65 scanf("%s %d", name[i], &val[i]); 66 int ans = 0, num = 0, cnt = 0; 67 while(n > 0) 68 { 69 n--; 70 int x = query(k, 1); 71 if(div[++cnt] > ans) 72 { 73 ans = div[cnt]; 74 num = x; 75 } 76 if(n == 0) 77 break; 78 if(val[x] > 0) 79 k = (k + val[x] - 2) % n + 1; 80 else 81 k = ((k + val[x] - 1) % n + n) % n + 1; 82 } 83 printf("%s %d\n", name[num], ans); 84 } 85 return 0; 86 }