Description
N children are sitting in a circle to play a game.
The children are numbered from 1 to N in clockwise order. Each of them has a card with a non-zero integer on it in his/her hand. The game starts from the K-th child, who tells all the others the integer on his card and jumps out of the circle. The integer on his card tells the next child to jump out. Let A denote the integer. If A is positive, the next child will be the A-th child to the left. If A is negative, the next child will be the (−A)-th child to the right.
The game lasts until all children have jumped out of the circle. During the game, the p-th child jumping out will get F(p) candies where F(p) is the number of positive integers that perfectly divide p. Who gets the most candies?
Input
Output
Output one line for each test case containing the name of the luckiest child and the number of candies he/she gets. If ties occur, always choose the child who jumps out of the circle first.
Sample Input
4 2 Tom 2 Jack 4 Mary -1 Sam 1
Sample Output
Sam 3
Source
【分析】
第二题.没什么好说的。
求素数用欧拉筛,dp求一下反素数。
然后注意一下细节,线段树直接上..其实树状数组也可以。
上一次使用树状数组做的,为什么我现在每个代码都有这么长?
1 /* 2 唐代杜甫 3 《月夜忆舍弟》 4 戍鼓断人行,边秋一雁声。(边秋 一作:秋边) 5 露从今夜白,月是故乡明。 6 有弟皆分散,无家问死生。 7 寄书长不达,况乃未休兵。 8 */ 9 #include <iostream> 10 #include <cstdio> 11 #include <algorithm> 12 #include <cstring> 13 #include <vector> 14 #include <utility> 15 #include <iomanip> 16 #include <string> 17 #include <cmath> 18 #include <queue> 19 #include <assert.h> 20 #include <map> 21 #include <ctime> 22 #include <cstdlib> 23 #include <stack> 24 #define LOCAL 25 const int MAXN = 500000 + 10; 26 const int MAXM = 1000000 + 10; 27 const int INF = 100000000; 28 const int SIZE = 450; 29 const int maxnode = 10000000 + 10; 30 using namespace std; 31 int n, k, people;//people为真实人数 32 bool have[MAXN]; 33 char str[MAXN][15]; 34 struct SEGTREE{ 35 struct Node{ 36 int sum, l, r; 37 int val;//代表权值 38 Node *ch[2]; 39 40 void update(){ 41 if (l == r) return; 42 sum = ch[0]->sum + ch[1]->sum; 43 return; 44 } 45 }*root, mem[maxnode]; 46 int tot;//静态数组 47 48 Node *NEW(int val){ 49 Node *p = &mem[tot++]; 50 p->val = val; 51 p->sum = 1; 52 p->ch[0] = p->ch[1] = NULL; 53 return p; 54 } 55 void init(){ 56 root = NULL; 57 tot = 1; 58 build(root, 1, n); 59 /*change(root, 1); 60 change(root, 2); 61 printf("%d\n", find(root, 2));*/ 62 } 63 void build(Node *&t, int l, int r){ 64 if (t == NULL){ 65 t = NEW(-1); 66 t->l = l; 67 t->r = r; 68 } 69 if (l == r){scanf("%s", str[l]);scanf("%d", &t->val); return;} 70 int mid = (l + r)>>1; 71 build(t->ch[0], l, mid); 72 build(t->ch[1], mid + 1, r); 73 t->update(); 74 } 75 //将x位置的sum变为0 76 int change(Node *&t, int l){ 77 if (t->l == l && t->r == l){ 78 t->sum = 0; 79 have[l] = 1;//出圈 80 return t->val; 81 } 82 int mid = (t->l + t->r)>>1; 83 int tmp; 84 if (l <= mid) tmp = change(t->ch[0], l); 85 if (l > mid) tmp = change(t->ch[1], l); 86 t->update(); 87 return tmp; 88 } 89 //返回 90 int find(Node *&t, int l){//找到第l个人,pos记录他的位置 91 if (t->l == t->r) return t->l; 92 int c = t->ch[0]->sum; 93 //if (l == (c + (have[t->ch[0]->r + 1] ^ 1))) return t->ch[0]->r + 1; 94 if (l <= c) return find(t->ch[0], l);//左边,右边 95 else return find(t->ch[1], l - c); 96 } 97 }A; 98 int prime[MAXN]; 99 int Max[MAXN], num[MAXN];//num记录i的约束个数 100 101 void prepare(){ 102 memset(prime, 0, sizeof(prime));//欧拉线性筛 103 prime[0] = 1; 104 for (int i = 2; i <= 500000; i++){ 105 if (!prime[i]) prime[prime[0]++] = i; 106 for (int j = 1; j < prime[0]; j++){ 107 if (prime[j] * i > 500000) break; 108 prime[i * prime[j]] = 1; 109 if (i % prime[j] == 0) break; 110 } 111 } 112 //DP+打表 113 num[0] = 0; 114 num[1] = Max[1] = 1; 115 num[498960] = 200;num[166320] = 160; 116 num[332640] = 192;num[110880] = 144; 117 num[277200] = 180; 118 num[221760] = 168; 119 int Ans = 1; 120 for (int i = 2; i <= 500000; i++){ 121 //printf("%d\n", num[Max[i - 1]]); 122 if (i >= 498960) {Max[i] = 498960;continue;} 123 if (i >= 332640) {Max[i] = 332640;continue;} 124 if (i >= 277200) {Max[i] = 277200;continue;} 125 if (i >= 221760) {Max[i] = 221760;continue;} 126 if (i >= 166320) {Max[i] = 166320;continue;} 127 if (i >= 110880) {Max[i] = 110880;continue;} 128 int cnt = 0, x = -1, tmp = i; 129 for (int j = 2; j <= (int)sqrt(1.0 * i); j++) if (i % j == 0) {x = j;break;} 130 if (x == -1) num[i] = 2;//质数 131 else{ 132 while (tmp % x == 0) {tmp /= x; cnt++;} 133 cnt = (cnt + 1) * num[tmp]; 134 num[i] = cnt; 135 } 136 if (num[i] > num[Ans]) Ans = i; 137 Max[i] = Ans; 138 } 139 } 140 void init(){ 141 memset(have, 0 ,sizeof(have));//表示第i个人是否出圈 142 people = n; 143 A.init(); 144 n = Max[n];//小于等于n的最大反素数 145 //找n个人出圈就行了 146 } 147 int MOD(int x, int t) {return x%t == 0? t: x % t;} 148 void work(){ 149 //if ( == 1) 150 int last = k;//表示上一个出圈人的名次 151 int t = A.change(A.root, k);//t为人手上的位置 152 //printf("%d", t); 153 for (int i = 2; i <= n; i++){//i为现在正在要出圈的人是第i个 154 //计算现在出圈人的名次 155 int now; 156 if (t < 0) now = MOD(MOD(last + t, people - (i - 1)) + (people - (i - 1)), (people - (i - 1))); 157 else now = MOD(MOD(last - 1 + t, people - (i - 1)) + (people - (i - 1)), (people - (i - 1))); 158 int tmp = A.find(A.root, now); 159 if (i == n) {printf("%s %d\n", str[A.find(A.root, now)], num[n]);return;} 160 t = A.change(A.root, tmp); 161 last = now; 162 } 163 /*A.change(A.root, 1); 164 A.change(A.root, 2); 165 printf("%d", A.find(A.root, 1));*/ 166 } 167 168 int main(){ 169 170 prepare(); 171 while (scanf("%d%d", &n, &k) != EOF){ 172 init(); 173 work(); 174 } 175 return 0; 176 }