题目描述:
个人思路:
- 首先明确这是一个区间DP问题,因为所有的数据都是有序的
- 转移条件为:
if (l[k][i] && r[k][j]) {
dp[i][j] = 1;
if (g[j + 1][k])
l[j + 1][i] = 1;
if (g[i - 1][k])
r[i - 1][j] = 1;
}
- 当[l,r]为[1,n]时说明符合题意,如果枚举结束时,到不了[1,n],说明不符合题意。
代码实现:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 770;
int n, a[maxn], dp[maxn][maxn], g[maxn][maxn], l[maxn][maxn], r[maxn][maxn];
int gcd(int x, int y) { return y == 0 ? x : gcd(y, x % y); }
void init() {
memset(l, 0, sizeof l);
memset(r, 0, sizeof r);
memset(dp, 0, sizeof dp);
for (int i = 1; i <= n; i++) {
l[i][i] = r[i][i] = dp[i][i] = 1;
for (int j = 1; j <= n; j++)
g[i][j] = gcd(a[i], a[j]) > 1;
}
}
void solve() {
scanf_s("%d", &n);
for (int i = 1; i <= n; i++) scanf_s("%d", &a[i]);
init();
for (int len = 1; len <= n; len++) {
for (int i = 1; i <= n - len + 1; i++) {
int j = i + len - 1;
for (int k = i; k <= j; k++) {
if (l[k][i] && r[k][j]) {
dp[i][j] = 1;
if (g[j + 1][k])
l[j + 1][i] = 1;
if (g[i - 1][k])
r[i - 1][j] = 1;
}
}
}
}
if (dp[1][n])
printf("Yes\n");
else
printf("No\n");
}
int main() {
int t;
scanf_s("%d", &t);
while (t--) {
solve();
}
return 0;
}