poj 2886 Who Gets the Most Candies?(线段树和反素数)

题目:http://poj.org/problem?id=2886

题意:N个孩子顺时针坐成一个圆圈且从1到N编号,每个孩子手中有一张标有非零整数的卡片。

第K个孩子先出圈,如果他手中卡片上的数字A大于零,下一个出圈的是他左手边第A个孩子。

否则,下一个出圈的是他右手边第(-A)个孩子。第p个出圈的孩子会得到F(p)个糖果,F(p)为p的因子数。求得到糖果数最多的是哪个孩子及得到多少糖果。

跟上一个 约瑟夫环的题目很像,就是加了一个反素数。

虽然我还是不太理解,但还是无耻的从别人的结题报告上把反素数表copy了下来。。。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <algorithm>
 6 using namespace std;
 7 const int maxn = 500000 + 10;
 8 int val[maxn];
 9 char name[maxn][20];
10 
11 int a[37]= {1,2,4,6,12,24,36,48,60,120,180,240,360,720,840,1260,1680,2520,5040,
12             7560,10080,15120,20160,25200,27720,45360,50400,
13             55440,83160,110880,166320,221760,277200,332640,498960,500001
14            };    //反素数表
15 int b[37]= {1,2,3,4,6,8,9,10,12,16,18,20,24,30,32,36,40,48,60,64,72,80,84,90,96,
16             100,108,120,128,144,160,168,180,192,200,1314521
17            };   //反素数对应的值
18 struct node
19 {
20     int l, r, sum;
21 }tr[maxn<<2];
22 
23 void build(int t, int l, int r)
24 {
25     tr[t].l = l;  tr[t].r = r;
26     tr[t].sum = r - l + 1;
27     if(l == r)
28         return;
29     int mid = (l+r)>>1;
30     build(2*t, l, mid);
31     build(2*t+1, mid+1, r);
32 }
33 int query(int num, int t)
34 {
35     tr[t].sum--;
36     if(tr[t].l == tr[t].r)
37     return tr[t].l;
38     if(tr[2*t].sum >= num)
39     return query(num, 2*t);
40     else
41     return query(num-tr[2*t].sum, 2*t+1);
42 }
43 int main()
44 {
45     int n, k, i, p, Max;
46     int x;
47     while(~scanf("%d%d", &n, &k))
48     {
49         i = 0;
50         Max = 0; p = 0;
51         while(a[i] <= n)
52         i++;
53         p = a[i-1]; Max = b[i-1];  //第几个出去的。最大值
54         build(1, 1, n);
55         for(i = 1; i <= n; i++)
56         scanf("%s%d",name[i], &val[i]);
57 
58         for(i = 0; i < p; i++)
59         {
60             n--;
61             x = query(k, 1);
62             if(n == 0)  break;
63             if(val[x] > 0)
64             k = (k-1+val[x]-1)%n + 1;
65             else
66             k = (k-1+val[x]%n+n)%n + 1;
67         }
68         printf("%s %d
",name[x], Max);
69     }
70     return 0;
71 }
原文地址:https://www.cnblogs.com/bfshm/p/3561837.html