POJ2886-Who Gets the Most Candies?(反素数)

本文介绍了一个有趣的问题:在特定的游戏规则下,哪位孩子能够获得最多的糖果。通过使用线段树等数据结构优化查找过程,文章提供了一种高效解决该问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Who Gets the Most Candies?
Time Limit: 5000MS Memory Limit: 131072K
Total Submissions: 14724 Accepted: 4634
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个孩子顺时针坐成一个圆圈且从1到n编号,每个孩子手中有一张标有非零整数的卡片。第k个孩子先出圈,如果他手中卡片上的数字a大于零,下一个出圈的是他左手边第a个孩子。否则,下一个出圈的是他右手边第(-a)个孩子。第p个出圈的孩子会得到F(p)个糖果,F(p)为p的因子数。求得到糖果数最多的是哪个孩子及得到多少糖果。

解题思路:这题用到了反素数,反素数的定义:对于任何正整数x,其约数的个数记做g(x)。如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数。设p为不大于N的反素数,则第p个出圈的孩子得到的糖果最多,为p的约数个数。出圈过程类似约瑟夫环。假设当前出圈的是剩余孩子中的第k个,他手中的数字为A。若A大于零,下一个出圈的就应该是剩余孩子中的第(k-1+a-1)%n+1个;若a小于零,下一个出圈的就应该是剩余孩子中的第((k-1+a)%n+n)%n+1个。查询剩余孩子中的第k个可以用线段树,线段树的每个节点的sum存储了所在区间还有多少孩子留下



#include <iostream>    
#include <cstdio>    
#include <string>    
#include <cstring>    
#include <algorithm>    
#include <cmath>    
#include <vector>    
#include <map>    
#include <set>    
#include <queue>    
#include <stack>    
#include <functional>    
#include <climits>    

using namespace std;

#define LL long long    
const int INF = 0x3f3f3f3f;

int a[40] = { 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 b[40] = { 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 };
char ch[500020][15];
int val[500020],x[2000100];

void build(int k, int l, int r)
{
	x[k] = r - l + 1;
	if (l == r) return;
	int mid = (l + r) >> 1;
	build(k<<1, l, mid);
	build(k<<1|1, mid + 1, r);
}

int query(int k,int l,int r,int p)
{
	x[k]--;
	if (l == r) return l;
	int mid = (l + r) >> 1;
	if (p <= x[k<<1]) return query(k<<1,l,mid,p);
	else return query(k<<1|1, mid+1,r,p - x[k<<1]);
}

int main()
{
	int n, k;
	while (~scanf("%d%d", &n, &k))
	{
		int i = 0,nn=n,pos;
		while (a[i] <= n) i++;
		int ma = b[i - 1],p = a[i - 1];
		for (int i = 1; i <= n; i++) scanf("%s%d", ch[i], &val[i]);
		build(1, 1, n);
		while (p--)
		{
			nn--;
			pos=query(1,1,n,k);
			if (!nn) break;
			if (val[pos] >= 0) k = (k - 1 + val[pos] - 1) % nn + 1;
			else k = ((k - 1 + val[pos]) % nn + nn) % nn + 1;
		}
		printf("%s %d\n",ch[pos], ma);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值