1. 程式人生 > 實用技巧 >CF264B Good Sequences

CF264B Good Sequences

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;
}