escription
![](https://img-blog.csdnimg.cn/2022010611561841831.png)
Input
![](https://img-blog.csdnimg.cn/2022010611561828834.png)
Output
![](https://img-blog.csdnimg.cn/2022010611561941825.png)
Sample Input
Sample 1: 4 2 3 6 4 9 8 12 1 Sample 2: 20 64978574415886122 263411 40589037247202745 239844 19724737874528206 167360 49216095485959384 760606 65063121727264647 659450 16572376111094320 726552 72014092598616298 133699 52843699826658793 427487 43374492289647376 552030 22047612465142862 605387 92386136280598953 718860 6436388687842008 368771 87727847161227820 880866 43622103777719758 352810 36870904328895185 322737 48993192459657624 456880 93250693206986868 619976 77407991580158822 861256 974508361120026 344635 77136053229840400 465474
Sample Output
Sample1: 51 Sample2: 101007480
Data Constraint
![](https://img-blog.csdnimg.cn/2022010611561988998.png)
分析
比较显然的是,某个子树一定是一段键值连续的区间
所以就是个区间DP,合并时判断是否满足GCD条件即可
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; typedef long long ll; const ll Inf=1ll<<62; const int N=310; struct Node { ll k,v; }a[N]; ll f[2][N][N],s[N],ans; bool g[N][N]; int n; ll GCD(ll a,ll b) {return !a?b:GCD(b%a,a);} bool CMP(Node a,Node b) {return a.k<b.k;} int main() { freopen("tree.in","r",stdin); freopen("tree.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%lld%lld",&a[i].k,&a[i].v); sort(a+1,a+n+1,CMP); for (int i=1;i<=n;i++) { s[i]=s[i-1]+a[i].v; for (int j=1;j<=n;j++) g[i][j]=GCD(a[i].k,a[j].k)>1ll?1:0; } for (int k=0;k<2;k++) for (int i=0;i<=n;i++) for (int j=0;j<=n;j++) f[k][i][j]=-Inf; for (int i=2;i<=n;i++) if (g[i][i-1]) f[1][i][i]=a[i].v; for (int i=1;i<n;i++) if (g[i][i+1]) f[0][i][i]=a[i].v; for (int len=1;len<n;len++) for (int l=1,r=l+len;r<=n;l++,r++) for (int j=l;j<=r;j++) { ll t=0; if (j==l) t=f[1][l+1][r]; else if (j==r) t=f[0][l][r-1]; else t=f[0][l][j-1]+f[1][j+1][r]; if (l>1&&g[j][l-1]) f[1][l][r]=max(f[1][l][r],t+s[r]-s[l-1]); if (r<n&&g[j][r+1]) f[0][l][r]=max(f[0][l][r],t+s[r]-s[l-1]); } ans=f[1][2][n]; for (int i=2;i<n;i++) ans=max(ans,f[0][1][i-1]+f[1][i+1][n]); ans=max(ans,f[0][1][n-1]);ans+=s[n]; if (ans>=0) printf("%lld",ans); else printf("-1"); }