junior19

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

reference:http://blog.csdn.net/acdreamers/article/details/8577673
Who Gets the Most Candies?
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

There are several test cases in the input. Each test case starts with two integers N (0 < N ≤ 500,000) and K (1 ≤ K ≤ N) 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

题意:N个人围成一圈,k值代表第k个人首先出局,然后该出局者的值代表下一个人出局的人,若该值为正数(比如3),则它左手边的第3个人出局,若为负数,则从右手边数起,每个人出局的顺序的因子数表示他能得到几颗糖,比如某人是第4个出局,他就有3颗糖(1,2,4共3个因子),问谁得到最多糖,以及它出局顺序的因子数目。

思路:先打个反素数表,反素数指拥有某因子数的最小的数,比如拥有3个因子的最小的数是4,拥有4个因子的最小的数是6,这样就能很快计算出n个人内第几个出局的人获得最多糖果了,接下来需要求这个人是谁,用线段树解决,节点保存该区间的空人数,然后是人坐标的计算,如第k个人出局它的值为num(正数),由于这个人已经出局了,需要将它前移一个位置即k-1,然后由于成环,要取模,计算时要减1处理,若果num为负数,则不需要前移或后移,直接减就行了,但是取模时还是得先减1,最后通过线段树的更新得到最终目标的位置。

# include <stdio.h>
# include <string.h>
# define lson l, m, id<<1
# define rson m+1, r, id<<1|1
# define MAXN 500000
int 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<aprime[cnt]; ++i)
        {
            if(a[pos].val > 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;
}


posted on 2017-03-09 20:44  junior19  阅读(228)  评论(0编辑  收藏  举报