Who Gets the Most Candies?
Case Time Limit: 2000MS
Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 8334 | Accepted: 2504 |
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 Inpu t
4 2
Tom 2
Jack 4
Mary -1
Sam 1
Sample Output
Sam 3
Source
POJ Monthly--2006.07.30, Sempr
题意:
有n个人顺时针围坐成一个圈,每个人手上都有一张卡片,开始去点第k个人,第k个人先退出,接着用刚才那第k个人手上的卡片去点名,正数顺时针点名,负数逆时针点名,重复执行,直到所有人都退出为止。每个人退出都可一得到糖果,第i个退出可以的到他的F(i)颗糖果。输出得到最多糖果的人的名字和糖果数,如果有糖果数相同的以先退出的为准。
F(i)即i元素的因子数之和。例:F(6)=4(1,2,3,6);F(15)=4(1,3,5,15);
思路:
1.例:F(1)=1;F(2)=2;F(3)=2;F(4)=3;F(5)=2;F(6)=4;可以看出F(i)不是线性增大的,所以在一个n范围内就有一个F(i)是最大的,需要用打表把他们处理出来。 见代码1,此程序效率并不高,见谅。
2.运用线段树单点更新,求出下一个人要退出的相对位置。例:假设共10个人,1,2,3,4......8,9,10;此时4,6,8已经退出,当前要退出的是第2个,第2个手里的卡片值是4,那么下一个要退出的确切位置是在第9个,而相对位置是第6个。
代码1,打表
/*************************************************************************
> File Name: 2886.cpp
> Author: BSlin
> Mail:
> Created Time: 2013年09月18日 星期三 13时18分28秒
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iterator>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#define MP make_pair
#define INF (1<<30)
#define PI acos(-1.0)
#define esp 1e-8
const int dx[4]={0,0,0,0};
using namespace std;
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#if defined (_WIN32) || defined (__WIN32) || defined (WIN32) || defined (__WIN32__)
#define LL __int64
#define LLS "%" "I" "6" "4" "d"
#else
#define LL long long
#define LLS "%" "l" "l" "d"
#endif
int mark[710],prime[130],sum_max,num_min;
int cnt,MAX;
void dfs(int sum,int num,int k,int limit) {
int i;
if(sum > sum_max) {
sum_max = sum;
num_min = num;
}
if(sum == sum_max && num < num_min) num_min = num;
if(k>=cnt) return ;
for(i=1;i<=limit;i++){
if(prime[k]*num>MAX) break;
num = prime[k] * num;
dfs(sum*(i+1),num,k+1,i);
}
}
int main(int argc, char** argv) {
//write;
memset(mark,0,sizeof(mark));
cnt = 0;
int ans;
for(int i=2;i<=709;i++){
if(mark[i] == 0) {
prime[cnt++] = i;
}
for(int j=0;j<cnt;j++){
if(i*prime[j]>709) break;
mark[i*prime[j]] = prime[j];
if(mark[i] == prime[j]) break;
}
}
ans = 0;
sum_max=0;
num_min=0;
for(MAX = 1;MAX<580000;MAX++){
dfs(1,1,0,25);
if(ans!=num_min){
printf("%d,",num_min);
ans = num_min;
}
}
printf("\n");
ans = 0;
sum_max=0;
num_min=0;
for(MAX = 1;MAX<580000;MAX++){
dfs(1,1,0,25);
if(ans!=sum_max){
printf("%d,",sum_max);
ans = sum_max;
}
}
return 0;
}
代码2,主代码
/*************************************************************************
> File Name: poj2886.cpp
> Author: BSlin
> Mail:
> Created Time: 2013年09月18日 星期三 13时03分09秒
************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iterator>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#define MP make_pair
#define INF (1<<30)
#define PI acos(-1.0)
#define esp 1e-8
const int dx[4]={0,0,0,0};
using namespace std;
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#if defined (_WIN32) || defined (__WIN32) || defined (WIN32) || defined (__WIN32__)
#define LL __int64
#define LLS "%" "I" "6" "4" "d"
#else
#define LL long long
#define LLS "%" "l" "l" "d"
#endif
#define M 500010
struct node {
int L,R,lnum,rnum;
}tree[M<<2];
char name[M][15];
int out[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,554400},candies[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,216};
//需要比500000大一些,原因看下面的注释
int pos[M],now_pos;
void up(int p) {
tree[p].lnum = tree[p<<1].lnum + tree[p<<1].rnum;
tree[p].rnum = tree[p<<1|1].lnum + tree[p<<1|1].rnum;
}
void build(int L,int R,int p) {
tree[p].L = L;
tree[p].R = R;
if(L == R) {
tree[p].lnum = 1;
tree[p].rnum = 0;
return ;
}
int mid = (L + R) >> 1;
build(L,mid,p<<1);
build(mid+1,R,p<<1|1);
up(p);
}
void update(int out_num,int p) {
if(tree[p].L == tree[p].R){
now_pos = tree[p].L;
tree[p].lnum = 0;
return;
}
if(out_num <= tree[p].lnum)
update(out_num,p<<1);
else if(out_num - tree[p].lnum <= tree[p].rnum)
update(out_num - tree[p].lnum,p<<1|1);
up(p);
}
int main(int argc, char** argv) {
read;
int n,k,i,candie,time;
while(scanf("%d%d",&n,&k) != EOF) {
build(1,n,1);
i=0;
while(out[i] <= n){ //当n在500000左右时,会发生错误
i++;
}
i--;
candie = candies[i];
time = out[i];
for(int i=1;i<=n;i++){
scanf("%s%d",&name[i][0],&pos[i]);
}
now_pos = 0;
pos[0] = 0;
int cc=n;
for(int i=time;i>=1;i--){
if(pos[now_pos]>0){
k = ((k + pos[now_pos] - 1) % cc + cc) % cc;
if(k == 0) k = cc;
}
else{
k = ((k + pos[now_pos]) % cc + cc) % cc;
if(k == 0) k = cc;
}
cc--;
update(k,1);
}
printf("%s %d\n",name[now_pos],candie);
}
return 0;
}