题目描述
题解
ymq怒草题解
一个数x能产生logx个不同的数,证明考虑当前的x能产生的区间,x/2时区间长最多+1
把a从大到小排序,再搞一个数组b,每次把ab中最大的数拆开丢到b的末尾,相同的合并一下即可,顺便可以维护答案数组
时间O(n log Mod)
code
#include <bits/stdc++.h>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define ll long long
#define file
using namespace std;
struct type{
int x;
ll s;
} b[3][29897352];
ll A,B,C,mod,a[1000001],m,l,r,mid,x;
int Q,n,i,j,k,h[3],t[3];
bool cmp(type a,type b) {return a.x>b.x;}
void add(int T,int x,ll s)
{
if (!x) return;
if (t[T] && b[T][t[T]].x==x) b[T][t[T]].s=b[T][t[T]].s+s;
else b[T][++t[T]]={x,s};
}
int main()
{
freopen("seat.in","r",stdin);
#ifdef file
freopen("seat.out","w",stdout);
#endif
scanf("%d",&n);
scanf("%lld%lld%lld%lld%lld",&a[1],&A,&B,&C,&mod);m=a[1];
fo(i,2,n) a[i]=(A*a[i-1]%mod*a[i-1]+B*a[i-1]+C)%mod+1;
sort(a+1,a+n+1);
fd(i,n,1) add(0,a[i],1),m+=a[i];
h[0]=h[1]=h[2]=1;
while (h[0]<=t[0] || h[1]<=t[1])
{
if (h[0]<=t[0] && h[1]<=t[1])
{
if (b[0][h[0]].x>b[1][h[1]].x)
add(2,b[0][h[0]].x,b[0][h[0]].s),add(1,b[0][h[0]].x/2,b[0][h[0]].s),add(1,(b[0][h[0]].x-1)/2,b[0][h[0]].s),++h[0];
else
if (b[0][h[0]].x<b[1][h[1]].x)
add(2,b[1][h[1]].x,b[1][h[1]].s),add(1,b[1][h[1]].x/2,b[1][h[1]].s),add(1,(b[1][h[1]].x-1)/2,b[1][h[1]].s),++h[1];
else
add(2,b[0][h[0]].x,b[0][h[0]].s+b[1][h[1]].s),add(1,b[0][h[0]].x/2,b[0][h[0]].s+b[1][h[1]].s),add(1,(b[0][h[0]].x-1)/2,b[0][h[0]].s+b[1][h[1]].s),++h[0],++h[1];
}
else
if (h[0]<=t[0])
add(2,b[0][h[0]].x,b[0][h[0]].s),add(1,b[0][h[0]].x/2,b[0][h[0]].s),add(1,(b[0][h[0]].x-1)/2,b[0][h[0]].s),++h[0];
else
add(2,b[1][h[1]].x,b[1][h[1]].s),add(1,b[1][h[1]].x/2,b[1][h[1]].s),add(1,(b[1][h[1]].x-1)/2,b[1][h[1]].s),++h[1];
}
fo(i,1,t[2]) b[2][i].s+=b[2][i-1].s;
scanf("%d",&Q);
for (;Q;--Q)
{
scanf("%lld",&x);
l=1;r=t[2];
while (l<r)
{
mid=(l+r)/2;
if (b[2][mid].s<x) l=mid+1; else r=mid;
}
printf("%d\n",b[2][l].x);
}
fclose(stdin);
fclose(stdout);
return 0;
}