【POJ2886】【线段树】Who Gets the Most Candies?

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

There are several test cases in the input. Each test case starts with two integers N (0 < N ≤ 500,000) and K (1 ≤ KN) on the first line. The next N lines contains the names of the children (consisting of at most 10 letters) and the integers (non-zero with magnitudes within 108) on their cards in increasing order of the children’s numbers, a name and an integer separated by a single space in a line with no leading or trailing spaces.

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 }
View Code

 

你可能感兴趣的:(get)