Who Gets the Most Candies?

Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 11303 Accepted: 3520
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
这道题可以用线段树做,是很有趣的一道,用到了约瑟夫环和反素数表。反素数的定义:对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数·在这道题中,要求的就是不超过n的最大反素数p,因为它的因数最多,即只要找出第p个跳出孩子的编号。另一个用到的是约瑟夫环公式,设跳出的小孩编号是k,当孩子拿的号码是正数A时,如果A=1,那么下个要跳出的编号是K,此时对应的A是1,那么可设起点编号是k-1,对应的A是0,则其通项公式是k=(k-1+A-1)%n+1;(这里采用先顺时针走A-1步,再顺时针走最后一步,是为了避免出现取余后结果是0的情况),如果A小于0,那么同理可以得到对应编号为0所对应的编号为k-1,采用先逆时针走-A-1,在顺时针走一步的方法,得到公式k=((k-1+A)%n+n)%n+1;注意这里的A对应的是最初原始排列的小孩手里拿的编号,是搜到的线段树的叶节点。
#include<stdio.h>
#include<string.h>
char s[500005][11];
int num[500005];
int a[37]={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,500001};
int c[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,100,108,120,128,144,160,168,180,192,200,1314521};
struct node
{
	int l,r,pos;
}b[4*500005];
void build(int l,int r,int i)
{
	int mid;
	b[i].l=l;b[i].r=r;
	if(l==r){
		b[i].pos=1;return;
	}
	mid=(l+r)/2;
	build(l,mid,i*2);
	build(mid+1,r,i*2+1);
	b[i].pos=b[i*2].pos+b[i*2+1].pos;
}


int update(int pos,int i)
{
	int mid;
	if(b[i].l==b[i].r){
		b[i].pos=0;return b[i].l;
	}
	b[i].pos--;
	if(b[i*2].pos>=pos){
		return update(pos,i*2);
	}
	else return update(pos-b[i*2].pos,i*2+1);
}


int main()
{
	int n,m,i,j,max,p,k,h;
	while(scanf("%d%d",&n,&k)!=EOF)
	{
		memset(s,0,sizeof(s));
		memset(num,0,sizeof(num));
		build(1,n,1);
		for(i=1;i<=n;i++){
			scanf("%s%d",s[i],&num[i]);
		}
		i=1;
		while(a[i]<=n){
			i++;
		}
		max=c[i-1];
		p=a[i-1];
		for(i=1;i<=p;i++){
			n--;
			h=update(k,1);         //h是最初始孩子的编号,也是线段树的叶节点 
			if(n==0)break;         //很重要! 
			if(num[h]>0)
			k=(k-1+num[h]-1)%n+1;
			else k=((k-1+num[h])%n+n)%n+1;
			//printf("%d\n",h);
		}
		printf("%s %d\n",s[h],max);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值