题解:
约瑟夫还+反素数
约瑟夫还:线段树处理
发素数:dfs
这个题dfs时,不加上限会超过int
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=500100;
int prime[13]={1,2,3,5,7,11,13,17,19,23};
struct TREE
{
int l,r;
int sum;
}tree[maxn*4];
char s[maxn*2][20];
int a[maxn*2];
int n,m,bestx,bestnum;
void dfs(int x,int k,int num,int limit)
{
if(x>n)return;
if(num>bestnum)
{
bestx=x;
bestnum=num;
}
else if(num==bestnum && x<bestx)
{
bestx=x;
}
int temp=1;
for(int i=1;i<=limit;i++)
{
temp*=prime[k];
if(x*temp>maxn)break;//不加这句话会搜爆,导致RE
dfs(x*temp,k+1,num*(i+1),i);
}
}
void build(int l,int r,int th)
{
tree[th].l=l;tree[th].r=r;tree[th].sum=0;
if(l==r)
{
tree[th].sum=1;
return;
}
int mid=(l+r)>>1;
build(l,mid,2*th);
build(mid+1,r,2*th+1);
tree[th].sum=tree[2*th].sum+tree[2*th+1].sum;
}
void add(int l,int r,int c,int th)
{
if(l==tree[th].l && r==tree[th].r)
{
tree[th].sum+=c;
return;
}
int mid=(tree[th].l+tree[th].r)>>1;
if(r<=mid)
add(l,r,c,2*th);
else if(l>mid)
add(l,r,c,2*th+1);
tree[th].sum=tree[2*th].sum+tree[2*th+1].sum;
}
int getnum(int l,int r,int th)
{
if(l>r)return 0;
if(tree[th].l==l && tree[th].r==r)
return tree[th].sum;
int mid=(tree[th].l+tree[th].r)>>1;
if(r<=mid)
return getnum(l,r,2*th);
else if(l>mid)
return getnum(l,r,2*th+1);
else
return getnum(l,mid,2*th)+getnum(mid+1,r,2*th+1);
}
int getlabel(int c,int th)
{
if(tree[th].l==tree[th].r)
{
return tree[th].l;
}
if(tree[2*th].sum>=c)
return getlabel(c,2*th);
else
return getlabel(c-tree[2*th].sum,2*th+1);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
scanf("%s%d",s[i],&a[i]);
bestx=1;bestnum=1;
dfs(1,1,1,20);
//xianduan
build(1,n,1);
int num=1,luck=m;
while(num<bestx)
{
//next
add(luck,luck,-1,1);
if(a[luck]>0)
{
a[luck]=a[luck]%(n-num);
if(a[luck]==0)a[luck]=n-num;
if(luck<n && getnum(luck+1,n,1)>=a[luck])
luck=getlabel(getnum(1,luck,1)+a[luck],1);
else
luck=getlabel(a[luck]-getnum(luck+1,n,1),1);
}
else
{
a[luck]=a[luck]%(n-num);
if(a[luck]==0)a[luck]=-(n-num);
if(luck>1 && getnum(1,luck-1,1)>=(-a[luck]))
luck=getlabel(getnum(1,luck,1)+1+a[luck],1);
else
luck=getlabel(getnum(1,n,1)-((-a[luck])-getnum(1,luck-1,1))+1,1);
}
num++;
}
printf("%s %d\n",s[luck],bestnum);
}
return 0;
}