week16实验 C宇宙狗的危机

在这里插入图片描述样例输入1:
1
6
3 6 9 18 36 108

样例输出1:
Yes

样例输入2:
2
2
7 17
9
4 8 10 12 15 18 33 44 81

样例输出2:
No
Yes
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
模拟课上的时候看到这题就没什么头绪,课下看了别人的代码才懂的。
区间DP,can_l[i][j]表示[i,j-1]是否可以作为j的左子树,can_r[i][j]表示[i+1,j]是否可以作为i的右子树,can_l[i][i],can_r[i][i]均为1,因为当i的左右子树为空时是符合的。
转移方程:if(g[l-1][k]>1) can_r[l-1][r]=1 if(g[r+1][k]>1) can_l[l][r+1]=1

#include<iostream>
#include<string.h>
#include<algorithm> 
#include<map> 
#include<string>
using namespace std;
int gcd(int a, int b) { return b == 0 ? a : gcd(b, a % b); }
int T;
int N;
int a[710];
int g[710][710];
bool can_l[710][710],can_r[710][710];
bool func()
{
	for(int len=1;len<=N;len++)
	{
		for(int l=1;l<=N-len+1;l++)
		{
			int r=l+len-1;
			for(int k=1;k<=r;k++)
			{
				if(can_l[k][l]&&can_r[k][r])
				{
					if(len==N)
					{
						return true;
					}
					if(g[l-1][k]>1)
						can_r[l-1][r]=1;
					if(g[k][r+1]>1)
						can_l[r+1][l]=1;
				}
			}
		}
	}
	return false;
}
int main()
{
	cin>>T;
	while(T--)
	{
		memset(g,0,sizeof(g));
		memset(can_l,0,sizeof(can_l));
		memset(can_r,0,sizeof(can_r));
		cin>>N;
		for(int i=1;i<=N;i++)
		{
			cin>>a[i];
		}
		for(int i=1;i<=N;i++)
		{
			for(int j=i;j<=N;j++)
			{
				g[i][j]=g[j][i]=gcd(a[i],a[j]);
			}
			can_l[i][i]=can_r[i][i]=1;
		}
		bool flag=func();
		
		if(flag)
			cout<<"Yes\n";
		else
			cout<<"No\n";
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章