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";
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章