题目链接 https://cn.vjudge.net/problem/POJ-2886
【题意】
N
N
N 个孩子顺时针坐成一个圆圈(编号从
1
1
1 到
N
N
N ),每个孩子手中有一张卡片(上有一个非0整数)现在让第K个孩子先淘汰,如果该孩子手中卡片上的数字A大于零,下一个出圈的是他左手边第A个孩子,否则,下一个出圈的是他右手边第A个孩子(当前孩子已经不算在圈中了)
第
p
p
p 个出圈的孩子会得到
F
(
p
)
F(p)
F(p) 个糖果,
F
(
p
)
F(p)
F(p) 为
p
p
p 的约数个数。输出得到糖果数最多的孩子名字和得到的糖果数。
【思路】
首先预处理所有数的约数个数,存入数组中.
假设当前出圈的是剩余孩子中的第
K
K
K 个(下标1开始),他手中的数字为
A
A
A 那么
A
>
0
A>0
A>0 下次被淘汰的是剩余孩子中的第
(
(
K
−
2
+
A
)
%
m
o
d
+
m
o
d
)
%
m
o
d
+
1
((K-2+A)\%mod+mod)\%mod+1
((K−2+A)%mod+mod)%mod+1 个
A
<
0
A<0
A<0 下次被淘汰的是剩余孩子中的第
(
(
K
−
1
+
A
)
%
m
o
d
+
m
o
d
)
%
m
o
d
+
1
((K-1+A)\%mod+mod)\%mod+1
((K−1+A)%mod+mod)%mod+1 个
上面的公式是先变成从0下标开始便于取模,最后取完模再+1. 其中
m
o
d
mod
mod是当前剩余的人数,每次都会-1,用线段树模拟
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define node tree[id]
#define lson tree[id<<1]
#define rson tree[id<<1|1]
using namespace std;
const int maxn=500005;
struct Tree{
int left,right;
int sum;
}tree[maxn<<2];
int n,k;
char s[maxn][15];
int a[maxn];
int fac[maxn];
void pushup(int id){ node.sum=lson.sum+rson.sum; }
void build(int id,int le,int ri){
node.left=le;
node.right=ri;
node.sum=ri-le+1;
if(le==ri) return;
int mid=(le+ri)>>1;
build(id<<1,le,mid);
build(id<<1|1,mid+1,ri);
}
int query(int id,int val){
if(node.left==node.right) return node.left;
if(lson.sum>=val) return query(id<<1,val);
else return query(id<<1|1,val-lson.sum);
}
void update(int id,int pos){
if(node.left==node.right){
node.sum=0;
return;
}
int mid=(node.left+node.right)>>1;
if(pos<=mid) update(id<<1,pos);
else update(id<<1|1,pos);
pushup(id);
}
void init(){
for(int i=1;i<maxn;++i){
for(int j=i;j<maxn;j+=i){
++fac[j];
}
}
}
int main(){
//freopen("in.txt","r",stdin);
init();
while(scanf("%d%d",&n,&k)==2){
for(int i=1;i<=n;++i) scanf("%s%d",s[i],&a[i]);
build(1,1,n);
int ans=-1,id=-1;
for(int cnt=1;cnt<=n;++cnt){
int pos=query(1,k);
//cout<<pos<<endl;
if(fac[cnt]>ans){
ans=fac[cnt];
id=pos;
}
if(cnt==n) break;
update(1,pos);
int mod=n-cnt;
if(a[pos]>0){
k=((k-2+a[pos])%mod+mod)%mod+1;
}
else if(a[pos]<0){
k=((k-1+a[pos])%mod+mod)%mod+1;
}
}
printf("%s %d\n",s[id],ans);
}
return 0;
}