2021牛客多校H - Hash Function (FTT)
题意
题解
如果存在\(a \equiv b \ {\rm mod} \ M\),即\(a-b \equiv 0 \ {\rm mod} \ M\),等价于\(a-b=kM\)。所以如果能求出所有可能的差值,就可以用O(nlogn)复杂度解决。
设\(f_i\)代表数\(i\)能够被表示,那么只需用\(f\)和{\(f_{500000-0}, f_{500000-1},f_{500000-2},...\)}卷积即可。卷积后如果\(f_{50000-i}\)大于0,代表存在差值为\(i\)。
最后从小到大枚举答案M,直到不存在差值为M的倍数。如果都存在,则答案就是500001。
#include <bits/stdc++.h>
#include <cmath>
#include <complex>
#define endl '\n'
#define IOS std::ios::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define FILE freopen(".//data_generator//in.txt","r",stdin),freopen("res.txt","w",stdout)
#define FI freopen(".//data_generator//in.txt","r",stdin)
#define FO freopen("res.txt","w",stdout)
#define mp make_pair
#define seteps(N) fixed << setprecision(N)
typedef long long ll;
using namespace std;
/*-----------------------------------------------------------------*/
ll gcd(ll a, ll b) {
return b ? gcd(b, a % b) : a;
}
#define INF 0x3f3f3f3f
double PI = acos(-1);
typedef std::complex<double> Complex; // STL complex
const Complex I(0, 1); // i
const int N = 2e6;
const int M = 5e5;
Complex tmp[N];
Complex f1[N], f2[N];
bool flag[M + 10];
int rev[N + 10];
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]]);
}
}
return;
}
void fft(Complex y[], int len, int on) {
change(y, len);
for(int h = 2; h <= len; h <<= 1) {
Complex wn(cos(2 * PI / h), sin(on * 2 * PI / h));
for(int j = 0; j < len; j += h) {
Complex w(1, 0);
for(int k = j; k < j + h / 2; k++) {
Complex u = y[k];
Complex t = w * y[k + h / 2];
y[k] = u + t;
y[k + h / 2] = u - t;
w = w * wn;
}
}
}
if(on == -1) {
for(int i = 0; i < len; i++) {
y[i] /= len;
}
}
}
int get(int x) {
int res = 1;
while(res < x) {
res = (res << 1);
}
return res;
}
int main() {
IOS;
int n;
cin >> n;
for (int i = 1; i <= n; i++) {
int v;
cin >> v;
f1[v] = Complex(1, 0);
f2[M - v] = Complex(1, 0);
}
int tot = get(2 * M + 1);
fft(f1, tot, 1);
fft(f2, tot, 1);
for (int i = 0; i < tot; i++) {
f1[i] *= f2[i];
}
fft(f1, tot, -1);
for (int i = 0; i <= M; i++) {
flag[i] = (bool)round(f1[M - i].real());
}
if(n == 1) cout << 1 << endl;
else {
bool f = false;
for(int i = 2; i <= M; i++) {
bool ok = true;
for(int j = i; j <= M; j += i) {
if(flag[j]) {
ok = false;
break;
}
}
if(ok) {
f = true;
cout << i << endl;
break;
}
}
if(!f) cout << 500001 << endl;
}
}