Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 14195 | Accepted: 4489 | |
Case Time Limit: 2000MS |
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 2Tom 2Jack 4Mary -1Sam 1
Sample Output
Sam 3
Source
思路:先打个反素数表,反素数指拥有某因子数的最小的数,比如拥有3个因子的最小的数是4,拥有4个因子的最小的数是6,这样就能很快计算出n个人内第几个出局的人获得最多糖果了,接下来需要求这个人是谁,用线段树解决,节点保存该区间的空人数,然后是人坐标的计算,如第k个人出局它的值为num(正数),由于这个人已经出局了,需要将它前移一个位置即k-1,然后由于成环,要取模,计算时要减1处理,若果num为负数,则不需要前移或后移,直接减就行了,但是取模时还是得先减1,最后通过线段树的更新得到最终目标的位置。
# include# include # define lson l, m, id<<1# define rson m+1, r, id<<1|1# define MAXN 500000int sum[MAXN<<2];struct node{ char name[11]; int val;}a[MAXN+3];const int aprime[]={1,2,4,6,12,24,36,48,60,120,180,240,360,720,840, 1260,1680,2520,5040,7560,10080,15120,20160,25200, 27720,45360,50400,55440,83160,110880,166320,221760, 277200,332640,498960,554400,665280 };const int fact[]={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,100,108,120,128,144,160,168,180, 192,200,216,224 };void init(int l, int r, int id){ sum[id] = r-l+1; if(l == r) return; int m = (l+r)>>1; init(lson); init(rson);}int Update(int p, int l, int r, int id){ --sum[id]; if(l == r) return r; int m = (l+r)>>1; if(sum[id<<1] >= p) return Update(p, lson); else return Update(p-sum[id<<1], rson);}int main(){ int n, k, &mod=sum[1]; while(~scanf("%d%d",&n,&k)) { init(1, n ,1); int pos = 0, cnt=0; for(int i=1; i<=n; ++i) scanf("%s%d",a[i].name, &a[i].val); a[pos].val = 0;//初始为0位置,那么第一个出局的人就不需要将下标前移1位。 while(cnt < 35 && aprime[cnt]<=n)//35是因为题目数据范围不会超过第35个反素数。 ++cnt; --cnt;//确定第cnt个出局者获得最多糖果。 for(int i=0; i 0) k = ((k-2+a[pos].val)%mod+mod)%mod + 1; else k = ((k-1+a[pos].val)%mod+mod)%mod + 1; pos = Update(k, 1, n, 1); } printf("%s %d\n",a[pos].name, fact[cnt]); } return 0;}