此题需要了解反素数的知识,之前不了解反素数还想把1e5以内的数的因子个数全部打表。。。。
此题还有一点,就是线段树的更新操作,删除某节点,这可能是大家之前没有接触到得
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAX=5*1e5+20;
typedef struct
{
char name[15];
int v;
}P;
P p[MAX];
int sum[4*MAX];
int N,K;
int RPrime[]={//反素数
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
};
int fact[]={//反素数约数个数
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
};
void build(int L,int R,int id)
{
sum[id]=R-L+1;
if(L==R)
return;
int mid=(L+R)>>1;
build(L,mid,id*2);
build(mid+1,R,id*2+1);
}
int update(int p,int L,int R,int id)
{
sum[id]--;
if(L==R)
return L;
int mid=(L+R)>>1;
if(p<=sum[id*2])
return update(p,L,mid,id*2);
else
return update(p-sum[id*2],mid+1,R,id*2+1);
}
int main()
{
int i,j,cnt;
while(~scanf("%d%d",&N,&K))
{
memset(sum,0,sizeof(sum));
cnt=0;
for(i=1;i<=N;i++)
scanf("%s%d",p[i].name,&p[i].v);
build(1,N,1);
for(int i=0;i<=35;i++)
{
if(RPrime[i]<=N)
cnt++;
}
cnt--;
int na,h=N;
for(i=1;i<=RPrime[cnt];i++)
{
na=update(K,1,N,1);
if(--h>0)
{
int v=p[na].v;
if(v>=0)
{
K=(K+v-1)%h;
if(K==0)
K+=h;
}
else
{
K=(K+v)%h;
if(K<=0)
K+=h;
}
}
}
cout<<p[na].name<<" "<<fact[cnt]<<endl;
}
return 0;
}