Who Gets the Most Candies? POJ - 2886 (线段树+筛法+模拟)
Who Gets the Most Candies?
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
题意:有n个小朋友顺时针围着坐了一圈,每个人手里都有一个数字。
游戏从第k个小朋友开始,首先,第k个小朋友退出游戏,
如果退出游戏的小朋友手上的数字是正整数A,则从他的左手边的第A个小朋友退出游戏,
如果退出游戏的小朋友手上的数字是负整数-A,则从他的右手边的第A个小朋友退出游戏。
第i个退出的小朋友可以获得f[i](i的约数的个数)个糖果,问最多糖果的小朋友的名字,并且他有多少糖果。
思路:
先通过筛法将个每个数字的约数个数存在数组F中,然后用线段树或者树状数组来模拟出环的过程。
首先我们将一个ch数组初始化为1,表示所有的孩子都在环中。
然后对于ch数组建树,如下图。
对于每一次出环的操作我们只需要知道这个孩子在当前队列中的位置 k,就可以通过线段树来查询,并更新对应节点的sum值为0。
sum[1]就记录了当前队列中剩下的孩子数量。
孩子的位置 k 可以通过对剩下的孩子数量取模得到。需要注意的是每次被选到的孩子会先退出队伍所以要先-1再取模。
对于每一次出队记录F[i]的最大值即可得到答案。
代码:
1 #include <set> 2 #include <map> 3 #include <list> 4 #include <stack> 5 #include <queue> 6 #include <deque> 7 #include <cmath> 8 #include <string> 9 #include <vector> 10 #include <cstdio> 11 #include <cstring> 12 #include <cstdlib> 13 #include <sstream> 14 #include <iostream> 15 #include <algorithm> 16 //#include <unordered_map> 17 #define INF 0x3f3f3f3f 18 #define ll long long 19 #define ull unsigned long long 20 #define FILL(a,n,v) fill(a,a+n,v) 21 #define Mset(a,v) memset(a,v,sizeof a) 22 #define fcio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0) 23 24 using namespace std; 25 const int maxn =5e5+10; 26 int F[maxn];//存约数个数 27 int sum[maxn<<2]; 28 struct s 29 { 30 string name; 31 int num; 32 }child[maxn]; 33 34 void init() 35 { 36 FILL(F,maxn,2); 37 F[1]=1; 38 for(int i=2;i+i<maxn;i++) 39 { 40 for(int j=i+i;j<maxn;j+=i) F[j]++; 41 } 42 } 43 44 void build(int l,int r,int root) 45 { 46 if(l==r) 47 { 48 sum[root]=1; 49 return ; 50 } 51 int mid=(r+l)>>1; 52 build(l,mid,root<<1); 53 build(mid+1,r,root<<1|1); 54 sum[root]=sum[root<<1]+sum[root<<1|1];//push_up 55 } 56 57 int update(int pos,int l,int r,int root) 58 { 59 if(l==r) 60 { 61 sum[root]=0; 62 return l; 63 } 64 int mid=(r+l)>>1; 65 int res; 66 if(pos<=sum[root<<1]) res=update(pos,l,mid,root<<1); 67 else res=update(pos-sum[root<<1],mid+1,r,root<<1|1); 68 sum[root]=sum[root<<1]+sum[root<<1|1];//push_up 69 return res; 70 } 71 72 int main() 73 { 74 fcio; 75 int n,k; 76 init(); 77 while(cin>>n>>k) 78 { 79 build(1,n,1); 80 for(int i=1;i<=n;i++) cin>>child[i].name>>child[i].num; 81 int now=0; 82 int maxvalue=0; 83 string maxname; 84 for(int i=1;i<=n;i++) 85 { 86 now=update(k,1,n,1); 87 if(F[i]>maxvalue) 88 { 89 maxvalue=F[i]; 90 maxname=child[now].name; 91 } 92 if(i==n) break; 93 if(child[now].num>0) k=(k+child[now].num-2)%sum[1]+1; 94 else k=((k+child[now].num-1)%sum[1]+sum[1])%sum[1]+1; 95 } 96 cout<<maxname<<' '<<maxvalue<<endl; 97 } 98 return 0; 99 }