2021牛客多校1 - Hash Function(思维+FFT)
題目鏈接:點擊查看
題目大意:給出一個長度為 nnn 的序列,現(xiàn)在要求找到一個 seedseedseed,使得所有數(shù)字變?yōu)?a[i]=a[i]modseeda[i]=a[i]\mod seeda[i]=a[i]modseed 后兩兩互不相同,找到最小的 seedseedseed
題目分析:考慮轉(zhuǎn)換模型,如果存在著 iii 和 jjj 使得 a[i]≡a[j](modseed)a[i] \equiv a[j] \pmod {seed}a[i]≡a[j](modseed),那么肯定有 a[i]+k?seed=a[j]a[i]+k*seed=a[j]a[i]+k?seed=a[j],其中 kkk 為任意正整數(shù),移項可得 a[i]?a[j]≡0(modseed)a[i]-a[j] \equiv 0 \pmod{seed}a[i]?a[j]≡0(modseed),到此模型轉(zhuǎn)換為尋找到最小的正整數(shù) mmm,其中不是任意一對 ∣a[i]?a[j]∣|a[i]-a[j]|∣a[i]?a[j]∣ 的約數(shù)。
直接按照項數(shù)枚舉的話復雜度是 n2n^2n2 級別的,觀察到值域是 [0,500000][0,500000][0,500000] 的,即 a[i],a[j]∈[0,500000]a[i],a[j] \in[0,500000]a[i],a[j]∈[0,500000],推得 ∣a[i]?a[j]∣∈[0,500000]|a[i]-a[j]|\in[0,500000]∣a[i]?a[j]∣∈[0,500000],因為本題中任意兩項的值都互不相等,所以可以從值域入手,判斷某個值是否存在,此時只需要枚舉答案 seedseedseed,就可以在 O(nlogn)O(nlogn)O(nlogn) 的時間復雜度內(nèi)檢查答案是否合法。
我們將 a[i]=xa[i]=xa[i]=x 轉(zhuǎn)換為 P[x]=1P[x]=1P[x]=1,令多項式 {P0,P1,...,P500000?1,P500000}\{ P_{0},P_{1},...,P_{500000-1},P_{500000} \}{P0?,P1?,...,P500000?1?,P500000?} 與 {P0,P?1,...,P?(500000?1),P?500000}\{ P_{0},P_{-1},...,P_{-(500000-1)},P_{-500000} \}{P0?,P?1?,...,P?(500000?1)?,P?500000?} 進行卷積,這樣對于其中的 P[i]P[i]P[i] 和 P[j]P[j]P[j],卷積后得到 P[i+j]P[i+j]P[i+j],因為 jjj (下標)是負數(shù),所以自然得到了所有的 Pi?jP_{i-j}Pi?j?
到此為止就可以用 ntt 或 fft 進行優(yōu)化了,不過多項式卷積不支持負數(shù),所以需要給會出現(xiàn)負數(shù)的位置增加一個偏移量 limitlimitlimit,令第二個多項式變?yōu)?#xff1a;{Plimit?0,Plimit?1,...,Plimit?(500000?1),Plimit?500000}\{ P_{limit-0},P_{limit-1},...,P_{limit-(500000-1)},P_{limit-500000} \}{Plimit?0?,Plimit?1?,...,Plimit?(500000?1)?,Plimit?500000?}
因為 ∣a[i]?a[j]∣∈[0,500000]|a[i]-a[j]|\in[0,500000]∣a[i]?a[j]∣∈[0,500000],所以最后枚舉答案的范圍是 [1,500001][1,500001][1,500001]
代碼:
// Problem: Hash Function // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/11166/H // Memory Limit: 524288 MB // Time Limit: 4000 ms // // Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2) // #pragma GCC optimize("Ofast","inline","-ffast-math") // #pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> #include<complex> #define cp complex < double > #define lowbit(x) (x&-x) using namespace std; const double pi=acos(-1); typedef long long LL; typedef unsigned long long ull; template<typename T> inline void read(T &x) {T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f; } template<typename T> inline void write(T x) {if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0'); } const int inf=0x3f3f3f3f; const int N=1e6+100;int lena=0,lenb=0,n,res[N<<2];cp F[N<<2],G[N<<2],arr[N<<2],inv[N<<2];void init() {for (int i=0;i<n;i++){arr[i]=cp(cos(2*pi*i/n),sin(2*pi*i/n));inv[i]=conj(arr[i]);} } void FFT(cp *a,cp *arr) {int lim=0;while ((1<<lim)<n) lim++;for (int i=0;i<n;i++){int t=0;for (int j=0;j<lim;j++)if ((i>>j) & 1) t|=1<<(lim-j-1);if (i<t) swap(a[i],a[t]);}for (int l=2;l<=n;l*=2){int m=l/2;for (cp *buf=a;buf!=a+n;buf+=l)for (int i=0;i<m;i++){cp t=arr[n/l*i]*buf[i+m];buf[i+m]=buf[i]-t;buf[i]+=t;}} } int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);lena=lenb=500000;read(n);for(int i=1;i<=n;i++) {int x;read(x);F[x].real(1);G[500000-x].real(1);}n=1;while(n<(lena+lenb))n<<=1;init();FFT(F,arr);FFT(G,arr);for(int i=0;i<n;i++)F[i]*=G[i];FFT(F,inv);for(int i=0;i<n;i++)res[i]=floor(F[i].real()/n+0.5);for(int i=1;i<=500001;i++) {bool flag=true;for(int j=500000+i;j<=1000000;j+=i) {if(res[j]) {flag=false;break;}}if(flag) {return 0*printf("%d\n",i);}}return 0; }總結(jié)
以上是生活随笔為你收集整理的2021牛客多校1 - Hash Function(思维+FFT)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2021牛客多校1 - Find 3-f
- 下一篇: 2021牛客多校1 - Journey