传送门
先来一波区间DP的套路
![f[l][r] = max(f[l][k]+f[k+1][r]) P5154 数列游戏 [区间DP]_#define](https://file.cfanz.cn/uploads/gif/2022/07/12/7/KP51W6C1Vf.gif)
![f[l][r] = max(f[l][r],f[l+1][r-1]+B[l]+B[r])(gcd(A[l],A[r]!=1)) P5154 数列游戏 [区间DP]_git_02](https://file.cfanz.cn/uploads/gif/2022/07/12/7/45B71bKYd1.gif)
记dp[i] 为1-i 的答案
![dp[i]=max(dp[i-1],dp[j-1]+f[j][i])(1<=j<=i-1) P5154 数列游戏 [区间DP]_git_03](https://file.cfanz.cn/uploads/gif/2022/07/12/7/01QP1Xf3JH.gif)
#include<bits/stdc++.h>
#define N 805
#define LL long long
#define inf 1000000000000000
using namespace std;
LL f[N][N], dp[N];
int A[N], B[N], n;
int read(){
  int cnt = 0; char ch = 0;
  while(!isdigit(ch)) ch = getchar();
  while(isdigit(ch)) cnt = cnt * 10 + (ch-'0'), ch = getchar();
  return cnt; 
}
int gcd(int a,int b){ return !b ? a : gcd(b, a%b);}
int main(){
  n = read();
  for(int i=1;i<=n;i++) A[i] = read();
  for(int i=1;i<=n;i++) B[i] = read();
  for(int i=1;i<n;i++) f[i][i+1] = (gcd(A[i],A[i+1])!=1) ? (B[i]+B[i+1]) : -inf;
  for(int len=4;len<=n;len+=2){
    for(int l=1;l<=n-len+1;l++){
      int r = l+len-1; f[l][r] = -inf;
      if(gcd(A[l], A[r]) != 1) f[l][r] = f[l+1][r-1] + B[l] + B[r];
      for(int k=l+1;k<r;k+=2) f[l][r] = max(f[l][r], f[l][k] + f[k+1][r]);
    }
  }
  for(int i=2;i<=n;i++){ 
    dp[i] = dp[i-1];
    for(int j=1;j<=i-1;j++)
      dp[i] = max(dp[i], dp[j-1] + f[j][i]);
  }
  printf("%lld",dp[n]); return 0;
}
                










