题目大意:给出一个有序数列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; }