约瑟夫环+线段树+反素数
自己写的代码,时间复杂度不太乐观,其实反素数表可以直接存,打表要2s+;
线段树存区间未被踢出的人数,每一次通过cur和dist找到下一个位置。
ACcode:
#include<stdio.h>
#include<iostream>
using namespace std;
const int size=500000;
struct People
{
char name[100];
int num;
}peo[size+10];
int cur;
int sum[size<<2];
int isprime[size+10],atp[size+10][2];
void antiprime()
{
int i,j;
for (i=1;i<=size;i++)
for (j=i;j<=size;j+=i)
atp[j][0]++;
for (i=1;i<=size;i++)
{
atp[i][1]=i;
if (atp[i][0]<atp[i-1][0])
{
atp[i][0]=atp[i-1][0];
atp[i][1]=atp[i-1][1];
}
else if (atp[i][0]==atp[i-1][0]&&
atp[i][1]>atp[i-1][1])
atp[i][1]=atp[i-1][1];
}
}
int modx(int aa,int bb)
{
int cc=aa/bb;
aa=aa-cc*bb;
return aa;
}
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int rt,int l,int r)
{
if (l==r)
{
sum[rt]=1;
return ;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(rt);
}
void update1(int rt,int l,int r,int cur)
{
if (l==r)
{
sum[rt]=0;
return ;
}
int mid=(l+r)>>1;
if (cur<=mid) update1(rt<<1,l,mid,cur);
else update1(rt<<1|1,mid+1,r,cur);
pushup(rt);
}
void update2(int rt,int l,int r,int dist)
{
if (l==r)
{
cur=r;
return ;
}
int mid=(l+r)>>1;
if (sum[rt<<1]>=dist) update2(rt<<1,l,mid,dist);
else update2(rt<<1|1,mid+1,r,dist-sum[rt<<1]);
}
int query(int rt,int l,int r,int L,int R)
{
if (L<=l&&r<=R) return sum[rt];
if (l==r) return 0;
int mid=(l+r)>>1,ans=0;
if (L<=mid) ans+=query(rt<<1,l,mid,L,R);
if (R>mid) ans+=query(rt<<1|1,mid+1,r,L,R);
return ans;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n,m,k,cnt,i,left,dist;
antiprime();
while (scanf("%d %d",&n,&k)!=EOF)
{
for (i=1;i<=n;i++) scanf("%s %d",peo[i].name,&peo[i].num);
cnt=atp[n][1];
build(1,1,n);
for (i=1,cur=k;i<cnt;i++)
{
dist=peo[cur].num;
update1(1,1,n,cur);
left=query(1,1,n,1,cur-1);
int flag=1;
if (dist<0) flag=-1;
dist=modx(dist,n-i);
if (dist==0) dist+=flag*(n-i);
if (dist>0)
{
if ((n-i-left)>=dist) update2(1,1,n,left+dist);
else
{
dist=dist-(n-i-left);
update2(1,1,n,dist);
}
}
else if (dist<0)
{
dist=-dist;
if (dist<=left) update2(1,1,n,left-dist+1);
else
{
dist=n-i+1+left-dist;
update2(1,1,n,dist);
}
}
}
printf("%s %d\n",peo[cur].name,atp[n][0]);
}
return 0;
}