2021牛客暑期多校训练营1 Hash Function(同余/NTT)

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营1 Hash Function(同余/NTT)相关的知识,希望对你有一定的参考价值。

LINK

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=k1m+s,a2=k2m+s

也就是 m m m ∣ a 1 − a 2 ∣ |a_1-a_2| a1a2的因子

所以现在就是求最小的 m m m满足 m m m不为 ∣ a i − a j ∣ |a_i-a_j| aiaj的因子,注意到 ∣ a i − a j ∣ < = 500000 |a_i-a_j|<=500000 aiaj<=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(vallog(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[xy+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牛客暑期多校训练营2

2021牛客暑期多校训练营4

2021牛客暑期多校训练营1 - F - Find 3-friendly Integers - 题解

2021牛客暑期多校训练营1 - F - Find 3-friendly Integers - 题解

2021牛客暑期多校训练营9

2021牛客暑期多校训练营3