CF264B Good Sequences
阿新 • • 發佈:2020-10-14
Solution
雖然每個題要求的最長序列的滿足條件不一樣,但是方法總是那一個——DP。
因為前後轉移和 \(\gcd\) 有關係,我們可以將 \(\gcd\) 用因子的方式表示。
我們設 \(dp_i\) 表示以 \(a_i\) 結尾的最長序列, \(f_i\) 為所有含有 \(i\) 這個因子的 \(a_x\) 中的 \(\max\{dp_x\}\) 。當方程轉移到 \(x\) 位時,列舉 \(a_x\) 的因子,更新 \(dp_x=\max\limits_{d|a_x,d\not=1}\{f_d\}+1\) ,然後再將 \(f_d\) 更新,最後搞一個 \(ans\) 記錄最大值就行了。
小細節:在更新 \(f_d\) 的時候,可以只更新質因子的 \(f\) ,因為在轉移的時候,用非質因子更新答案,其實在列舉質因子的時候就已經更新過了,並且質因子的答案不會比非質因子差。而且 \(dp\) 陣列也不需要,當列舉到某一位時,這一位以前的最大值已經求出,所以可以直接和 \(ans\) 更新。
程式碼
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; const int N=100010; int ans,n,a[N],f[N]; inline int read(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();} return x*f; } inline void solve(int x){ int m=sqrt(x),sum=0; for(int i=2;i<=m;i++) if(x%i==0) sum=max(max(sum,f[i]),f[x/i]); sum=max(sum,f[x]);//記得x也算x的因數 for(int i=2;i<=m;i++) if(x%i==0){ f[i]=sum+1; while(x%i==0) x/=i; } f[x]=sum+1; ans=max(ans,sum+1);//不記錄dp[] 直接更新 } int main(){ n=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) solve(a[i]); printf("%d\n",ans); return 0; }