H
思路
很容易想到如果,那么。因此如果我们求出的集合,就可以将问题转化为找最小的一个数,使得它和它的倍数没有在中出现过。
朴素做法求是的,考虑如何优化。
构造一个多项式,如果在中出现过,就把的系数设为,否则设为。再构造一个多项式,如果在中出现过,就把的系数设为,反之同理。
两个多项式相乘,就可以得到新的多项式,根据的定义可以发现如果中的系数不为,这一项必然是由中系数不为的项与中系数不为的项相乘得到,代表存在。因此就是刚开始要求的集合。
多项式相乘的过程用快速傅里叶变换优化,复杂度为。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define en puts("")
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
void read() {}
void OP() {}
void op() {}
template <typename T, typename... T2>
inline void read(T &_, T2 &... oth)
{
int __=0;
_=0;
char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-')
__=1;
ch=getchar();
}
while(isdigit(ch))
{
_=_*10+ch-48;
ch=getchar();
}
_=__?-_:_;
read(oth...);
}
template <typename T>
void Out(T _)
{
if(_<0)
{
putchar('-');
_=-_;
}
if(_>=10)
Out(_/10);
putchar(_%10+'0');
}
template <typename T, typename... T2>
inline void OP(T _, T2... oth)
{
Out(_);
putchar('\n');
OP(oth...);
}
template <typename T, typename... T2>
inline void op(T _, T2... oth)
{
Out(_);
putchar(' ');
op(oth...);
}
const int N=1<<21,M=5E5+1,P=998244353,G=3,Gi=332748118;
ll n,m,lim=1<<20,len=20,x;
ll inv[N],a[N],b[N],vis[N];
ll ksm(ll x,ll y)
{
ll ret=1;
while(y)
{
if(y&1)
ret=(ret*x)%P;
x=(x*x)%P;
y>>=1;
}
return ret;
}
ll check(ll x)
{
for(int i=x;i<=M;i+=x)
{
if(vis[i])
return 0;
}
return 1;
}
void ntt(ll *c,ll ty)
{
rep(i,0,lim-1)
if(i<inv[i])
swap(c[i],c[inv[i]]);
for(ll m=2;m<=lim;m<<=1)
{
ll wn=ksm(ty==1?G:Gi,(P-1)/m);
for(int k=0;k<lim;k+=m)
{
ll w=1;
ll cel=m>>1;
rep(j,0,cel-1)
{
ll t=w*c[k+j+cel]%P;
ll u=c[k+j];
c[k+j]=(u+t)%P;
c[k+j+cel]=(u-t+P)%P;
w=(w*wn)%P;
}
}
}
}
void print()
{
rep(i,1,lim)
{
if(a[i])
{
op(i,a[i],a[4]);
en;
}
}
}
int main()
{
read(n);
rep(i,1,n)
{
read(x);
a[x]=1;
b[M-x]=1;
}
rep(i,0,lim-1)
inv[i]=(inv[i>>1]>>1) | ((i&1)<<(len-1));
ntt(a,1);
ntt(b,1);
rep(i,0,lim)
a[i]=a[i]*b[i];
ntt(a,-1);
ll inv_=ksm(lim,P-2);
rep(i,0,lim)
{
ll tmp=a[i]*inv_%P;
if(tmp>0)
vis[abs(i-M)]=1;
}
rep(ans,n,M)
{
if(check(ans))
{
OP(ans);
break;
}
}
}