POJ 2886 Who Gets the Most Candies?(线段树+反素数)

原创 2018年04月16日 23:10:16
Who Gets the Most Candies?
Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 15617 Accepted: 4944
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

POJ Monthly--2006.07.30, Sempr

题意:有n个熊孩子按顺时针的顺序围成一圈坐着,每个熊孩子手中都有一张写着一个数字的卡片。首先第k个熊孩子跳出圈,并且给其他熊孩子看他手中卡片上的数字是多少,如果数字是正数A那么在他左手边第A个熊孩子就是下一个要跳出圈的,反之如果是负数-A那么就是右手边第A个熊孩子跳出圈。如此往复,直到所有的熊孩子都出圈了游戏则结束了。每一个出圈的熊孩子都会得到糖果的奖励,得到糖果的个数为F(p),p的值代表的是第几个跳出圈,F(p)表示的是p的约数的个数。问哪个熊孩子得到的糖果最多。

思路:我们要找的那个熊孩子为F(p)最大,也就是要找出1~n中约数最多的那个数。这里就要用到反素数了,什么是反素数呢?令G(x)等于x约数的个数,那么对于任意一个小于x的数i都满足G(i)<G(x)的话,x即为反素数。所以我们要找的也就是1~n中最大的反素数,但是光找出最大反素数还不够。因为虽然我们知道是第几个跳出圈的熊孩子能得到最多的糖果,但是咱们并不知道他的名字呀。

所以这里就要用线段树来模拟这个游戏的过程了,建一颗线段树来表示区间内还有几个熊孩子。每一次更新操作都根据游戏规则让一个熊孩子出圈,也就是将一个叶子节点置为0,这样其他表示区间内有几个熊孩子的值也会相应变化。在更新节点的时候,如果左子树剩余的熊孩子比我们要找的熊孩子的序号大,直接在左子树中找,如果不够的话,那么在右子树中找的话就得把序号减去左子树中熊孩子的个数,这样才能正确找到要出圈的熊孩子。

另外还有一点要注意的是,因为每一次熊孩子都得出圈,那么如果熊孩子手中卡片上的值m为正数的话,后面熊孩子的相对位置就都得减一了。例如刚开始五个熊孩子,第一个出圈的是第三个孩子,随后第四个孩子就变成了第三个,第五个就变成了第四个,都依次往前推了一个。所以下一个要出圈的孩子的序号应该要在原来的基础上再减一,也就是k+m-1。如果m是负数的话就不需要减一,也就是k+m。

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N=500050;
struct node
{
    int l,r;
    int num;
}segTree[4*N];

struct child
{
    char name[15];
    int val;
}c[N];
void build(int root,int l,int r)
{
    segTree[root].l=l;
    segTree[root].r=r;
    if(l==r)
    {
        segTree[root].num=1;
        return;
    }
    int mid=(l+r)>>1;
    build(root<<1,l,mid);
    build(root<<1|1,mid+1,r);
    segTree[root].num=segTree[root<<1].num+segTree[root<<1|1].num;
}

int update(int root,int index)
{
    segTree[root].num--;
    if(segTree[root].l==segTree[root].r)
    {
        segTree[root].num=0;
        return segTree[root].r;
    }
    if(index<=segTree[root<<1].num)
        return update(root<<1,index);
    else
        return update(root<<1|1,index-segTree[root<<1].num);//左子树中剩余人数不够,那么就得在右子树中找到不够的那一部分,所以得减去左子树中的人数

}
int RPrime[]={//反素数
    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
};

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
};
int main()
{
    int n,k,i;
    while(scanf("%d %d",&n,&k)!=EOF)
    {
        int cnt=0;
        while(RPrime[cnt]<=n)
        {
            cnt++;
        }
        cnt--;
        for(i=1;i<=n;i++)
            scanf("%s %d",c[i].name,&c[i].val);
        int mod=n;
        build(1,1,n);
        int pos=0;
        c[pos].val=0;
        for(i=0;i<RPrime[cnt];i++)
        {
            if(c[pos].val>0)
                k=((k+c[pos].val-2)%mod+mod)%mod+1;
            else
                k=((k+c[pos].val-1)%mod+mod)%mod+1;
            pos=update(1,k);
            mod--;
        }
        printf("%s %d\n",c[pos].name,fact[cnt]);
    }
    return 0;
}

POJ 2886 Who Gets the Most Candies?(线段树模拟约瑟夫环,高合成数)

POJ 2886 Who Gets the Most Candies?(线段树模拟约瑟夫环,高合成数) ACM 题目地址:POJ 2886 Who Gets the Most Candie...
  • hcbbt
  • hcbbt
  • 2014-08-15 10:08:51
  • 1725

poj2886Who Gets the Most Candies?(线段树,记活人的数量,题目类似约瑟夫环)

Description N children are sitting in a circle to play a game. The children are numbered from 1 ...
  • u010372095
  • u010372095
  • 2013-10-30 21:39:57
  • 1044

POJWho Gets the Most Candies?

这题想了好久才弄懂,首先题意是要求最先出队且获得的糖果数最多的人,所以只需要在循环中每次判断此时出队的人获得的糖果数是否比别人多 #include #include #include #inc...
  • u013748887
  • u013748887
  • 2014-09-03 11:04:18
  • 716

POJ 2886 Who Gets the Most Candies?(线段树)

题意: N个小孩围成一圈,他们被顺时针编号为 1 到 N。每个小孩手中有一个卡片,上面有一个非 0 的数字,游戏从第 K 个小孩开始,他告诉其他小孩他卡片上的数字并离开这个圈,他卡片上的数字 A 表明...
  • u012962816
  • u012962816
  • 2014-11-11 12:59:28
  • 451

Who Gets the Most Candies? - POJ 2886 线段树

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072K Total Submissi...
  • u014733623
  • u014733623
  • 2014-09-11 23:24:42
  • 358

POJ 2886 Who Gets the Most Candies? (线段树)

Description N children are sitting in a circle to play a game. The children are numbered from 1 ...
  • u013923947
  • u013923947
  • 2014-08-04 15:31:34
  • 489

POJ 2886 Who Gets the Most Candies? (线段树)

题意:模拟约瑟夫环。有N(1并离开这个圈,他卡片上的数字 A 表明了下一个离开的小孩,如果 A 是大于 0 的,则下个离开的是左手边第 A 个,如果是小于 0 的,则是右手边的第 A 个小孩。游戏...
  • u010679062
  • u010679062
  • 2013-08-02 09:26:22
  • 1330

POJ - 2886 Who Gets the Most Candies?(线段树)

Who Gets the Most Candies? Time Limit: 5000MS   Memory Limit: 131072KB   64bit IO Format: %I64d ...
  • qq_18738333
  • qq_18738333
  • 2015-04-02 14:25:12
  • 464

POJ 2886 Who Gets the Most Candies? 线段树

http://poj.org/problem?id=2886 题意: N个人玩一个游戏,每个人都有一个weight ,游戏从第K个人开始,第一轮标号为K的人退出游戏,下一个退出的人的编号由上一轮退...
  • ivan_zjj
  • ivan_zjj
  • 2012-06-30 22:32:34
  • 647

poj 2886 Who Gets the Most Candies?(线段树)

题目链接:poj 2886 Who Gets the Most Candies? 题目大意:N个人围成一圈玩约瑟夫环游戏,不同的是,步长不固定,由前一个出局的人决定,给定K表示起始的人。第i个淘...
  • u011328934
  • u011328934
  • 2014-09-18 16:41:00
  • 750
收藏助手
不良信息举报
您举报文章:POJ 2886 Who Gets the Most Candies?(线段树+反素数)
举报原因:
原因补充:

(最多只允许输入30个字)