版权声明:布呗之路的守望者 https://blog.csdn.net/hypHuangYanPing/article/details/82117971
/**
链接:https://codeforces.com/contest/1025/problem/D
题意:给出n个数 将这些数构造成一颗二叉树 问是否存在这样的二叉树使得树上任意相邻两点的gcd>1;
分析:pre[i][j] 表示点i j是否能构成一条边 pre[i][j]=gcd(a[i],a[j])>1;
fl[i][j]:j向左扩展是否能连通i;
fr[i][j]::i向右扩展是否能连通j;
可选择枚举区间长度进行暴力 看所在区间的每个点是否能够连通 一步一步进行前后状态的转移
转移后若能得到当len==n时,fl[i][j] 或者fr[i][j]存在即可;
*/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=705;
int n,a[maxn],pre[maxn][maxn],fl[maxn][maxn],fr[maxn][maxn];
int gcd(int x,int y){return y==0?x:gcd(y,x%y);}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
pre[i][j]=(gcd(a[i],a[j])>1),pre[j][i]=pre[i][j];
for(int i=1;i<=n;i++) fl[i][i]=fr[i][i]=1;
for(int len=1;len<=n;len++){
for(int l=1;l<=n-len+1;l++){
int r=l+len-1;
for(int k=l;k<=r;k++){
if((!fl[k][l])||(!fr[k][r])) continue;
if(len==n) { puts("Yes");return 0;}
if(pre[l-1][k]) fr[l-1][r]=1;
if(pre[k][r+1]) fl[r+1][l]=1;
}
}
}
puts("No");
return 0;
}