2021牛客暑期多校训练营1 Hash Function(同余/NTT)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营1 Hash Function(同余/NTT)相关的知识,希望对你有一定的参考价值。
n n n个数模 m m m各不相同
考虑若 a 1 a_1 a1和 a 2 a_2 a2模完相同,那么有
a 1 = k 1 ∗ m + s , a 2 = k 2 ∗ m + s a_1=k_1*m+s,a_2=k_2*m+s a1=k1∗m+s,a2=k2∗m+s
也就是 m m m为 ∣ a 1 − a 2 ∣ |a_1-a_2| ∣a1−a2∣的因子
所以现在就是求最小的 m m m满足 m m m不为 ∣ a i − a j ∣ |a_i-a_j| ∣ai−aj∣的因子,注意到 ∣ a i − a j ∣ < = 500000 |a_i-a_j|<=500000 ∣ai−aj∣<=500000
所以可以预处理 [ 1 , 500000 ] [1,500000] [1,500000]中哪些数可能作为差值出现
预处理了之后,可以暴力枚举 m m m然后枚举 m m m的倍数看看是否存在这样的差值,存在就不合法
这部分复杂度为 O ( v a l ∗ l o g ( v a l ) ) O(val*log(val)) O(val∗log(val))(其中 v a l val val表示值域)
预处理差值可以使用 F F T / N T T \\rm FFT/NTT FFT/NTT
具体来说,就是令 f [ a i ] = 1 f[a_i]=1 f[ai]=1,再令 g [ − a i ] = 1 g[-a_i]=1 g[−ai]=1
然后 f f f和 g g g卷一下就可以得到差值,然而数组不能存负数,于是给 − a i -a_i −ai设置一个偏移量 b a s e base base
让数组 f [ a i ] f[a_i] f[ai]和数组 g [ − a i + b a s e ] g[-a_i+base] g[−ai+base]卷一下即可
这样如果存在数字 x , y x,y x,y,就存在 f [ x ] f[x] f[x]和 g [ − y + b a s e ] g[-y+base] g[−y+base](其中 x > y x>y x>y)
这样卷完之后得到的数组 s [ x − y + b a s e ] s[x-y+base] s[x−y+base]一定有值
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 2e6+10;
const int base = 500000;
const int mod = 998244353, G = 3, Gi = 332748118;
int quick(int x,int n)
{
int ans = 1;
for( ; n ; n>>=1,x=x*x%mod )
if( n&1 ) ans = ans*x%mod;
return ans;
}
int n,m,a[maxn],f[maxn],g[maxn],r[maxn];
bool ok[base+2];
void NTT(int *a,int type,int limit)
{
for(int i=0;i<limit;i++)
if( i<r[i] ) swap( a[i],a[r[i]] );
for(int mid=1;mid<limit;mid<<=1)
{
int wn = quick( type==1?G:Gi,(mod-1)/(mid<<1) );
for(int R=mid<<1,i=0;i<limit;i+=R )
for(int k=0,w=1;k<mid;k++,w=w*wn%mod )
{
int x = a[i+k], y = w*a[i+k+mid]%mod;
a[i+k] = (x+y)%mod, a[i+k+mid] = (x-y+mod)%mod;
}
}
}
int limit,l;
void mul(int a[],int b[],int n,int m)
{
limit = 1;
while( limit<=n+m ) limit <<= 1,l++;
for(int i=0;i<limit;i++)
r[i] = (r[i>>1]>>1 ) | ( (i&1)<<(l-1) );
NTT(a,1,limit); NTT(b,1,limit);
for(int i=0;i<limit;i++) a[i] = a[i]*b[i]%mod;
NTT(a,-1,limit);
int inv = quick(limit,mod-2);
for(int i=0;i<=n+m;i++) a[i] = a[i]*inv%mod;
}
signed main()
{
cin >> n;
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++) f[a[i]] = 1, g[base-a[i]] = 1;
mul( f,g,base,base );
for(int i=0;i<=base+base;i++)
{
if( f[i] )
ok[abs(i-base)] = 1;
}
for(int m=2;;m++)
{
int flag = 0;
for(int j=m;j<=base;j+=m) flag |= ok[j];
if( flag==0 ){ cout << m; return 0; }
}
}
以上是关于2021牛客暑期多校训练营1 Hash Function(同余/NTT)的主要内容,如果未能解决你的问题,请参考以下文章
2021牛客暑期多校训练营1 - F - Find 3-friendly Integers - 题解