Codeforces-566F

题目大意:给出一个有序数列a,这个数列中每两个数,如果满足一个数能整除另一个数,则这两个数中间是有一条边的,现在有这样的图,求最大联通子图。

题解:并不需要把图搞出来,可以直接dp,$f[i]$表示以第$i$个数为开头的最大的联通子图,转移类似最长上升子序列,$f[i]=max(f[i],f[j]+1)$

Code:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
inline int read()
{
    int x=0,f=1; char ch=getchar();
    while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
#define MAXN 1000010
int N,a[MAXN],dp[MAXN],ans,id[MAXN];
int main()
{
    N=read();
    for (int i=1; i<=N; i++) a[i]=read(),id[a[i]]=i;
    for (int i=1; i<=N; i++) dp[i]=1;
    for (int i=1,now=a[i]; i<=N; i++,now=a[i])
        while (now+a[i]<=a[N]) now+=a[i],dp[id[now]]=max(dp[id[now]],dp[i]+1);
    for (int i=1; i<=N; i++) ans=max(ans,dp[i]);
    printf("%d\n",ans);
    return 0;
}
566F

相关文章: