原题传送门
首先会想到一个朴素的暴力
表示区间
根为
是否可行,枚举两边子树的根
复杂度
这是逆推dp,一般逆推不行,可以想一想顺推
对于一个区间
,它的父亲只能为
,可以枚举区间
以及区间的根
,往
两个状态推
这样复杂度是
跑不满,可以接受
Code:
#include <bits/stdc++.h>
#define maxn 710
using namespace std;
int a[maxn], dp[maxn][maxn][2], g[maxn][maxn], n;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int gcd(int m, int n){ return !n ? m : gcd(n, m % n); }
int main(){
n = read();
for (int i = 1; i <= n; ++i) a[i] = read(), dp[i][i][0] = dp[i][i][1] = 1;
for (int i = 1; i <= n; ++i)
for (int j = i + 1; j <= n; ++j) g[i][j] = gcd(a[i], a[j]);
for (int l = 1; l <= n; ++l)
for (int i = 1, j = i + l - 1; j <= n; ++i, ++j)
for (int k = i; k <= j; ++k)
if (dp[i][k][1] && dp[k][j][0]){
if (i == 1 && j == n) return puts("Yes"), 0;
if (g[i - 1][k] > 1) dp[i - 1][j][0] = 1;
if (g[k][j + 1] > 1) dp[i][j + 1][1] = 1;
}
puts("No");
return 0;
}