版权声明:本文为博主原创文章,转载请附上原博客链接。 https://blog.csdn.net/Dale_zero/article/details/82119270
题目链接:http://codeforces.com/problemset/problem/1025/D
开两个dp数组代表从i到j能否形成以i为根的右子树或者以j为根的左子树。
若有一位置到1和n均能形成左右子树则输出Yes,否则输出No
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
#define mod 1000000007
#define For(i,m,n) for(int i=m;i<=n;i++)
#define Dor(i,m,n) for(int i=m;i>=n;i--)
#define LL long long
#define lan(a,b) memset(a,b,sizeof(a))
#define sqr(a) a*a
using namespace std;
int dp[710][710][2];
int g[710][710];
int a[710];
int n;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
bool pin()
{
For(len,1,n)
{
for(int i=1;i+len-1<=n;i++)
{
if(len==1)
dp[i][i][0]=1,dp[i][i][1]=1;
int j=i+len-1;
// printf("i=%d j=%d\n",i,j);
For(k,i,j)
{
// printf("k=%d\n",k);
if(dp[i][k][0]==1&&dp[k][j][1]==1)
{
// cout<< "ok1" << endl;
if(i==1&&j==n)
return true;
if(j!=n&&g[k][j+1]==1)
dp[i][j+1][0]=1;///printf("dp[%d][%d][%d]=1\n",i,j+1,0);
if(i!=1&&g[i-1][k]==1)
dp[i-1][j][1]=1;///printf("dp[%d][%d][%d]=1\n",i-1,j,1);
}
}
}
}
return false;
}
int main()
{
while(~scanf("%d",&n))
{
lan(dp,0);
lan(a,0);
lan(g,0);
For(i,1,n)
scanf("%d",&a[i]);
For(i,1,n)
For(j,i+1,n)
if(gcd(a[i],a[j])!=1)g[i][j]=1;
sort(a+1,a+1+n);
if(pin())
printf("Yes\n");
else
printf("No\n");
}
return 0;
}