Who Gets the Most Candies?
Time Limit : 10000/5000ms (Java/Other) Memory Limit : 262144/131072K (Java/Other)
Total Submission(s) : 33 Accepted Submission(s) : 13
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?
4 2 Tom 2 Jack 4 Mary -1 Sam 1
Sam 3
题意:
第一行输入两个数n,k,分别代表n个人和一开始最先跳出的位置k,接下来输入n个人的名字和所拥有的数字num,这n个人顺时针坐在一圈,首先第k个人先出环,再当num为正数时顺时针走num步,那么数到的这个人就跳出环,以此类推,当num为负数时,逆时针走(-num)步,第m个跳出的人得m的不重复因子的个数(v )个糖果。求出得到得到最多的糖果的人,如果有多个一样的求最先跳出的,输出名子和得到糖果的数量.
思路:
线段树,先求出n个人中是第几个人跳出来得到的糖果最多,然后进行模拟,线段树的作用是线段树的节点中保存该区间剩下的人的个数,然后运用update进行删除操作,没update一次,删除一个人。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define L(rt) (rt<<1)
#define R(rt) (rt<<1|1)
const int N=500000;
int n,id,maxx;//id用来记录最大的位置,maxx用来求最大的值
int candy[N+5];
struct person{
char name[15];
int num;
}a[N+5];
struct Tree{
int l,r;
int sum;//表示线段树节点中剩余的人的个数
}p[4*N];
void go(){//计算因子,并求n范围内因子个数最多的一个数
memset(candy,0,sizeof(candy));
for(int i=1;i<=n;i++){
candy[i]++;
for(int j=i+i;j<=n;j+=i)
candy[j]++;
}
maxx=candy[1];
id=1;
for(int i=2;i<=n;i++)
if(candy[i]>maxx){
maxx=candy[i];
id=i;
}
}
void build(int l,int r,int pos){
p[pos].l=l;
p[pos].r=r;
p[pos].sum=r-l+1;
if(l==r)
return;
int mid=(l+r)>>1;
build(l,mid,L(pos));
build(mid+1,r,R(pos));
}
int update(int k,int pos){
p[pos].sum--;
if(p[pos].l==p[pos].r){
return p[pos].l;
}
if(p[L(pos)].sum>=k)
return update(k,L(pos));
else
return update(k-p[L(pos)].sum,R(pos));
}
int main(){
ios::sync_with_stdio(false);
int i,k;
while(cin>>n>>k){
go(); //一开始这个函数调用的位置出现错误,wa了两发
for(i=1;i<=n;i++){
cin>>a[i].name>>a[i].num;
}
build(1,n,1);
int maxn=id;
int tid;
for(i=0;i<maxn;i++){
n--;
tid=update(k,1);//原始的位置
if(n==0)break;
if(a[tid].num>0)//表示左起
k=(k-1+a[tid].num-1)%n+1; //下一次跳出环的人的编号
else//表示右起
k=((k-1+a[tid].num)%n+n)%n+1;
}
cout<<a[tid].name<<' '<<maxx<<endl;
}
return 0;
}