Hash Function —— 1H
Hash Function
题目描述
给定一个序列\(a\),找到一个最小的\(seed\)满足\(h(x) = x \; \% \; seed\),且任意两个数模意义下不一样。
范围
\(n \leq 5 \times 10^5,a_i \leq 10^5\)
题解
题目可以转化为找到一个最小的数\(m\),使得其不是任何一个\(|a_i - a_j|\)的约数。
设\(h(A)\)表示\(A\)是否存在,那么\(h(A) = h(i) * h(A - i)\),计算卷积即可,判断每一种差值是否存在。
使用\(FFT\)加速上述过程。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 2e6 + 10;
const double PI = acos(-1.0);
struct Complex {
double x,y;
Complex (double _x = 0.0,double _y = 0.0) {
x = _x,y = _y;
}
Complex operator - (const Complex &b) const {
return Complex (x - b.x,y - b.y);
}
Complex operator + (const Complex &b) const {
return Complex (x + b.x,y + b.y);
}
Complex operator * (const Complex &b) const {
return Complex (x * b.x - y * b.y,x * b.y + y * b.x);
}
};
int rev[N];
void change (Complex y[],int len) {
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(y[i],y[rev[i]]);
}
}
void fft(Complex y[],int len,int op) {
change(y,len);
for(int h = 2;h <= len;h <<= 1) {
Complex wn (cos(2 * PI / h),sin (op * 2 * PI / h));
for(int j = 0;j < len; j += h) {
Complex w(1,0);
for(int k = j;k < j + (h >> 1); ++k) {
Complex u = y[k];
Complex t = w * y[k + (h >> 1)];
y[k] = u + t;
y[k + (h >> 1)] = u - t;
w = w * wn;
}
}
}
if(op == -1) {
for(int i = 0;i < len; ++i) {
y[i].x /= len;
}
}
}
int n;
int sum[N];
Complex x1[N],x2[N];
int mx = -1;
int main () {
cin >> n;
for (int i = 0;i < n; ++i) {
int x;
scanf("%d",&x);
x1[x].x = 1;
mx = max(mx,x);
}
mx = 500001;
int len = 0;
while((1 << len) <= mx << 1) len ++;
len = 1 << len;
for(int i = 1;i < len; ++i) {
x2[i].x = (x1[len - i].x > 0);
}
x2[0].x = x1[0].x;
fft(x1,len,1);fft(x2,len,1);
for(int i = 0;i < len; ++i) {
x1[i] = x1[i] * x2[i];
}
fft(x1,len,-1);
for(int i = 0;i < len; ++i) {
sum[i] = int(x1[i].x + 0.5);
}
for(int i = 1;i <= mx; ++i) {
bool ok = 0;
for(int j = i;j <= mx;j += i) {
ok |= (sum[j] > 0);
}
if(!ok) {
cout << i << endl;
break;
}
}
return 0;
}