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

来源:互联网 发布:网络盒子怎样双清 编辑:程序博客网 时间:2024/05/31 18:42

Who Gets the Most Candies?
Time Limit: 5000MS Memory Limit: 131072KTotal Submissions: 14724 Accepted: 4634Case 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 2Tom 2Jack 4Mary -1Sam 1

Sample Output

Sam 3

Source

POJ Monthly--2006.07.30, Sempr


题意: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;}

阅读全文
0 0