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
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;
}