Hash Function
题意:给出数组,求最小的mod使得 每个数取模后都不同。
思路:a%p=b%p 等价于 (a-b)%p=0 ,所以p不能为数组中任意两个数的差 ,假设我们现在知道了存在哪些差值,那么我们可以枚举倍数的方法求最小的p,
求所有差值可以用fft ,可以转化为(xa1+xa2+xa3+……+xan)*(x-a1+x-a2+x-a3+……+x-an) 系数大于0的那个指数就是存在的差值
负数可以加个500001;
fft的代码
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf=2e18+100;
const int maxn=(int)1e6+10000;
const double PI=acos(-1);
int len=1;
int rev[maxn<<1];
int a[maxn],cnt[maxn];
struct comple
{
double x;
double y;
comple(double x=0,double y=0):x(x),y(y) {}
comple operator + (const comple b)const
{
return comple(x+b.x,y+b.y);
}
comple operator - (const comple b)const
{
return comple(x-b.x,y-b.y);
}
comple operator * (const comple b)const
{
comple ans;
ans.x=x*b.x-y*b.y;
ans.y=x*b.y+y*b.x;
return ans;
}
} c[maxn<<1],b[maxn<<1];
void change(comple f[])
{
for(int i=0; i<len; i++)
{
rev[i]=rev[i>>1]>>1;
if(i&1)rev[i]|=len>>1;
}
for(int i=0; i<len; i++)
{
if(i<rev[i])//保证只交换一次
swap(f[i],f[rev[i]]);
}
}
void fft(comple f[],int op)
{
change(f);
for(int h=2; h<=len; h<<=1)
{
comple wn{cos(2*PI/h),sin(op*2*PI/h)};
for(int j=0; j<len; j+=h)
{
comple w{1,0};
for(int k=j; k<j+h/2; k++)
{
comple u=f[k];
comple v=w*f[k+h/2];
f[k]=u+v;
f[k+h/2]=u-v;
w=w*wn;
}
}
}
if(op==-1)
{
for(int i=0; i<len; i++)
{
f[i].x=f[i].x/len+0.5;
}
}
}
signed main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[a[i]].x=1;
c[500001-a[i]].x=1;
}
while(len<1000001) len<<=1;
fft(b,1);
fft(c,1);
for(int i=0;i<len;i++) b[i]=b[i]*c[i];
fft(b,-1);
for(int i=0;i<=len;i++)
{
if((int)b[i].x>0)
{
cnt[abs(500001-i)]=1;
}
}
for(int i=n;;i++)
{
bool fg=1;
for(int j=i;j<=500001;j+=i)
{
if(cnt[j])
{
fg=0;break;
}
}
if(fg)
{
cout<<i<<"\n";
return 0;
}
}
}
NTT的代码
#include <bits/stdc++.h>
#define int long long
#define ll long long
using namespace std;
const int maxn = 5e6+7;
const int mod = 998244353;
const int G = 3;
int n,m,L,R[maxn];
int A[maxn],B[maxn];
ll qpow(ll a,ll b)
{
ll ans = 1;
while(b>0)
{
if(b&1) ans = ans*a%mod;
b>>=1;
a = a*a%mod;
}
return ans%mod;
}
void NTT(int *a,int f)
{
for(int i = 0; i < n; i++)
{
if(i < R[i]) swap(a[i],a[R[i]]);
}
for(int i = 1; i < n; i <<= 1)
{
ll gn = qpow(G,(mod - 1) / (i << 1));
for(int j = 0; j < n; j += (i << 1))
{
ll g = 1;
for(int k = 0; k < i; k++, g = g * gn % mod)
{
int x = a[j + k], y = g * a[j + k + i] % mod;
a[j + k] = (x + y) % mod;
a[j + k + i] = (x - y + mod) % mod;
}
}
}
if(f==1) return;
int inv = qpow(n,mod - 2);
reverse(a + 1,a + n);
for(int i = 0; i < n; i++) a[i] = 1ll * a[i] * inv % mod;
}
void solve(int *A,int *B)
{
m = 1000001;
for(n = 1; n <= m; n <<= 1) L++;
for(int i = 0; i < n; i++) R[i] = (R[i >> 1] >> 1) | ((i & 1) << (L - 1));
NTT(A,1);
NTT(B,1);
for(int i = 0; i < n; i++) A[i] = 1ll * A[i] * B[i] % mod;
NTT(A,-1);
}
int a[maxn],cnt[maxn];
signed main()
{
scanf("%lld",&n);
int n2=n;
for(int i=1; i<=n; i++)
{
cin>>a[i];
A[a[i]]=1;
B[500001-a[i]]=1;
}
solve(A,B);
for(int i=0; i<=m; i++)
{
if(A[i]>0)
{
cnt[abs(500001-i)]=1;
}
}
for(int i=n2;; i++)
{
bool fg=1;
for(int j=i; j<=500001; j+=i)
{
if(cnt[j])
{
fg=0;
break;
}
}
if(fg)
{
cout<<i<<"\n";
return 0;
}
}
}