Who Gets the Most Candies?
题目
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?
题意
N个孩子从1到N面对面顺时钟坐成一圈,从第一次是第k个孩子开始出圈,下一次就是这个孩子的第A个孩子出圈,A为正数从左数,A为负从右数,第p个出圈的的孩子可以得到F(p)个糖果,F(p)为p的约数的个数,输出得到最多糖果的人的名字和糖果数。
思路
题目要求的最大的F(p)就是小于n的约数最多的数,可以先预处理出来,剩下的就是找出第p个人。出圈第p个人可以模拟依次求出,线段树储存的是该位置是否有人,也就是未出圈的为1,出圈的位置为0。线段树用来查找1到n内的还未出圈的第k个人的编号。
在一个人出圈后要推出下一个出圈人的编号。
k表示1到n中的第k个还未出圈的人,当A>0时,下一个出圈人是从1开始第k = ((k - 1 + child[pos].val - 1) % mod + mod) % mod + 1 个未出圈的人;当A<0时,k = ((k - 1 + child[pos].val) % mod + mod) % mod + 1 。mod是还在圈内的人数,每次出圈都要减一,因为取模是从0开始,所以要先减一,取模后加一,A>0是多减一是因为当第k个人出圈时,k之后的下标都要减一,而A<0时不减。
#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 5e5 + 10;
struct node
{
int l, r, val;
}t[MAXN * 4];
struct n
{
char s[100];
int val;
}child[MAXN];
int y[MAXN], id;
void init(int n)
{
for (int i = 1; i <= n; i++)
{
for (int j = i; j <= n; j += i)
y[j]++;
}
id = 1;
int maxx = y[1];
for (int i = 2; i <= n; i++)
{
if(maxx < y[i])
{
maxx = y[i];//预处理出最多糖果数
id = i;
}
}
}
void pushup(int n)
{
t[n].val = t[n * 2].val + t[n * 2 + 1].val;
}
void build(int n, int l, int r)
{
t[n].l = l;
t[n].r = r;
if(l == r)
{
t[n].val = 1;
return;
}
int mid = (l + r) / 2;
build(n * 2, l, mid);
build(n * 2 + 1, mid + 1, r);
pushup(n);
}
int update(int n, int pos)//找出还在圈内的第k个人的编号
{
int l = t[n].l, r = t[n].r;
if(l == r)
{
t[n].val--;
return l;
}
int mid = (l + r) / 2, res;
if(pos <= t[n * 2].val) res = update(n * 2, pos);
else res = update(n * 2 + 1, pos - t[n * 2].val);
pushup(n);
return res;
}
int main()
{
int n, k;
while (~scanf("%d %d", &n, &k))
{
init(n);
for (int i = 1; i <= n; i++)
{
scanf("%s %d", child[i].s, &child[i].val);
}
build(1, 1, n);
int pos = 0, mod = t[1].val;
child[0].val = 0;
int ans_id = id;
while (id--)
{
if(child[pos].val > 0)
k = ((k - 1 + child[pos].val - 1) % mod + mod) % mod + 1;
else
k = ((k - 1 + child[pos].val) % mod + mod) % mod + 1;
pos = update(1, k);
mod = t[1].val;
}
printf("%s %d\n", child[pos].s, y[ans_id]);
}
}