2021牛客多校
阿新 • • 發佈:2021-07-19
Hash Function
題意
給一個數列長度為\(n\)的數列\(a\),找一個最小的\(seed\),使得數列\(a\)中所有數模\(seed\)後的值全都不一樣。
題解
若數字\(x\),\(y\)模\(seed\)後的值一樣,假設\(x>y\),那麼必定存在整數\(k\),使得\(y-x=k\times seed\)。
所以,我們要找的那個\(seed\),不能是任何兩個數的差值的因數,於是我們就需要預處理出任意兩個數之間的差值的絕對值,樸素演算法是\(n^2\)的,必定會超時,於是考慮\(FFT\)和\(NTT\)。
眾所周知,離散域上的卷積的定義為
\[c_i=\sum_{j=0}^na_j \times b_{i-j} \]其中向量\(c\)
如何用卷積處理差值呢?在這裡我們是\(a_j\)和\(b_{i-j}\)乘,那麼如果設\(a_i=1\)表示\(i\)這個差值存在,\(b_i\)同理,他們他倆相乘的結果不就表示他們下標對應的差值存在麼?C++沒有負下標,於是我們令\(b\)的下標從 \(5e^5\)開始即可,最後處理時,和\(5e^5\)取個差的絕對值就好了。
最後求值的時候用埃氏篩篩一下就行了。
AC程式碼
#include <bits/stdc++.h> // #define IO ios::sync_with_stdio(NULL) #define sc(z) scanf("%d", &(z)) #define _ff(i, a, b) for (ll i = a; i <= b; ++i) #define _rr(i, a, b) for (ll i = b; i >= a; --i) #define _f(i, a, b) for (ll i = a; i < b; ++i) #define _r(i, a, b) for (ll i = b - 1; i >= a; --i) #define mkp make_pair #define endl "\n" #define lowbit(x) x&(-x) #define pb push_back using namespace std; typedef double db; typedef long long ll; typedef long double ld; const int N = 2e6 + 5; const int M = 1e6 + 5; const ll mod = 1e9 + 7; const double eps = 1e-9; const double pi = acos(-1.0); const int maxn = 500000; struct Complext { db a, b; Complext(){} Complext(db r, db i):a(r),b(i){} }a[N], b[N]; Complext operator + (Complext a, Complext b) { return Complext(a.a + b.a, a.b + b.b); } Complext operator - (Complext a, Complext b) { return Complext(a.a - b.a, a.b - b.b); } Complext operator * (Complext a, Complext b) { return Complext(a.a * b.a - a.b * b.b, a.a * b.b + a.b * b.a); } int mp[M]; int lim = 1, len, rev[N]; void fft(Complext c[], db flag) { //int cnt = 0; _f(i, 0, lim) if (i < rev[i]) swap(c[i], c[rev[i]]); _f(i, 0, len) { int m = 1<<i; Complext wn = Complext(cos(pi / m), flag * sin(pi / m)); for (int j = 0; j < lim; j += (m<<1)) { Complext w = Complext(1, 0); for (int k = 0; k < m; k++, w = w * wn) { Complext u = c[j + k], t = w * c[m + j + k]; c[j + k] = u + t; c[m + k + j] = u - t; //cnt++; } } } if (flag == -1) _ff(i, 0, lim) a[i].a /= lim; } int main() { // IO; #ifndef ONLINE_JUDGE freopen("a.in", "r", stdin); // freopen("a.out", "w", stdout); #endif // !ONLINE_JUDGE int n, x; cin >> n; for (int i = 0; i < n; ++i) { cin >> x; a[x].a = 1; b[maxn - x].a = 1; } // while (lim <= maxn + maxn) lim <<= 1, len++; lim = 1<<20, len = 20; _f(i, 0, lim) rev[i] = (rev[i>>1]>>1)|((i&1)<<(len-1)); fft(a, 1); fft(b, 1); _f(i, 0, lim) a[i] = a[i] * b[i]; fft(a, -1); _f(i, 0, lim) { int tmp = (int)(a[i].a + 0.5); if (tmp > 0) mp[abs(i - maxn)] = 1; } // _ff(i, 1, 10) cout<<mp[i]<<" ";cout<<endl; _ff(i, n, maxn+1) { int flag = 1; for (int j = i; j <= maxn+1; j += i) { if (mp[j]) { flag = 0; break; } } if (flag) { cout << i << endl; break; } } return 0; }