CF1398G Running Competition 题解
设 \(c_i=0/1\) 表示 \(i\) 有没有在 \(a\) 中出现,那么这个就是他自己和自己的差卷积,卷出来之后不是 \(0\) 的位置就都可以,每个可以的位置更新一下自己的倍数就行(或者使用狄利克雷前缀和,不过暴力做复杂度也过得去)。
差卷积就翻一下序列然后 FFT 就行了。
点击查看代码
const int N=8e5+13,M=1e6+13;
const int G=114514,Gi=qpow(G,mod-2);
int n,m,in[N],a[N],b[N],c[M],r[N];
inline void fft(int *f,int limit,int type){
for(int i=0;i<limit;++i)
if(i<r[i]) swap(f[i],f[r[i]]);
for(int mid=1;mid<limit;mid<<=1){
int Wn=qpow(type==1?G:Gi,(mod-1)/(mid<<1));
for(int j=0;j<limit;j+=(mid<<1)){
int w=1;
for(int k=0;k<mid;++k,w=1ll*w*Wn%mod){
int x=f[j+k],y=1ll*w*f[j+k+mid]%mod;
f[j+k]=(x+y)%mod;f[j+k+mid]=(x-y+mod)%mod;
}
}
}
if(type==1) return;
int inv=qpow(limit,mod-2);
for(int i=0;i<limit;++i) f[i]=(ll)f[i]*inv%mod;
}
inline void mul(int *a,int *b){
int limit=1,l=0;
while(limit<=(m<<1)) limit<<=1,++l;
for(int i=0;i<limit;++i) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
fft(a,limit,1),fft(b,limit,1);
for(int i=0;i<limit;++i) a[i]=(ll)a[i]*b[i]%mod;
fft(a,limit,-1);
}
int main(){
read(n),read(m);int ll;read(ll);
for(int i=1;i<=n+1;++i){
int x;read(x);
a[x]=b[m-x]=1;
}
mul(a,b);int lim=1e6;
for(int i=m+1;i<=(m<<1);++i){
if(!a[i]) continue;
int l=(i-m+ll)<<1;
for(int j=l;j<=lim;j+=l) c[j]=max(c[j],l);
}
int q;read(q);
while(q--){
int x;read(x);
if(!c[x]) print(-1),print(' ');
else print(c[x]),print(' ');
}
return 0;
}