题意描述
在瑞神大战宇宙射线中我们了解到了宇宙狗的厉害之处,虽然宇宙狗凶神恶煞,但是宇宙狗有一个很可爱的女朋友。
最近,他的女朋友得到了一些数,同时,她还很喜欢树,所以她打算把得到的数拼成一颗树。
这一天,她快拼完了,同时她和好友相约假期出去玩。贪吃的宇宙狗不小心把树的树枝都吃掉了。所以恐惧包围了宇宙狗,他现在要恢复整棵树,但是它只知道这棵树是一颗二叉搜索树,同时任意树边相连的两个节点的gcd(greatest common divisor)都超过1。
但是宇宙狗只会发射宇宙射线,他来请求你的帮助,问你能否帮他解决这个问题。
补充知识:
GCD:最大公约数,两个或多个整数共有约数中最大的一个 ,例如8和6的最大公约数是2。
一个简短的用辗转相除法求gcd的例子:
int gcd(int a,int b){return b == 0 ? a : gcd(b,a%b);}
输入
输入第一行一个t,表示数据组数。
对于每组数据,第一行输入一个n,表示数的个数
接下来一行有n个数,输入保证是升序的。
输出
每组数据输出一行,如果能够造出来满足题目描述的树,输出Yes,否则输出No。
无行末空格。
输入样例 1
1
6
3 6 9 18 36 108
1
2
3
输出样例 1
Yes
1
输入样例 2
2
2
7 17
9
4 8 10 12 15 18 33 44 81
1
2
3
4
5
输出样例2
No
Yes
![](https://img-blog.csdnimg.cn/img_convert/eb26f5b8455559d6f1d2235a8ab9231b.png)
思路:
dp构建可行二叉搜索树!
所有的数据都是有序的,可以考虑区间dp。to_l[i][j]代表[i,j-1]是否可作为j的左子树。to_r[i][j]表示[i+1,j]是否可以作为i的右子树。
转移条件为:if (GCD[l-1][root]>1)R[l-1][r]=1; if (GCD[r+1][root]>1)L[l][r+1]=1;
当[l,r]为[1,n]时说明可以构建符合题意的树,如果枚举结束都到不了[1,n]说明不可以构建符合题意的树。GCD数组记录两点gcd.
初始化时注意将 to_l[i][i]和to_r[i][i]都赋值为1,因为当点i的左子树或者右子树为空时一定是符合题意的
代码:
1 #include<iostream>
2 #include<cstring>
3 using namespace std;
4 const int maxn=770;
5 int n,t;
6 int a[maxn],GCD[maxn][maxn] ;
7 bool to_l[maxn][maxn],to_r[maxn][maxn];
8
9 int gcd(int a,int b){
10 return b == 0 ? a : gcd(b,a%b);
11 }
12 bool solve()
13 {
14 for(int len=1;len<=n;len++)
15 {
16 for(int l=1;l<=n-len+1;l++)
17 {
18 int r=l+len-1;
19 for(int k=l;k<=r;k++)
20 {
21 if(to_l[k][l] && to_r[k][r])
22 {
23 if(len==n)
24 {
25 return true;
26 }
27 if(GCD[l-1][k] > 1)
28 to_r[l-1][r]=1;
29 if(GCD[k][r+1] > 1)
30 to_l[r+1][l]=1;
31 }
32 }
33 }
34 }
35 return false;
36 }
37 void init(){
38 memset(to_l,0,sizeof(to_l));
39 memset(to_r,0,sizeof(to_r));
40 for(int i=1;i<=n;i++)
41 {
42 for(int j=i;j<=n;j++)
43 {
44
45 GCD[j][i]=gcd(a[i],a[j]);
46 GCD[i][j]=GCD[j][i];
47 }
48 to_l[i][i]=1;
49 to_r[i][i]=1;
50 }
51 }
52 int main()
53 {
54 cin>>t;
55 while(t--)
56 {
57 //input
58 cin>>n;
59 for(int i=1;i<=n;i++)
60 cin>>a[i];
61 //initialize
62 init();
63 //solve
64 bool flag = solve();
65 if(flag){
66 cout<<"Yes"<<endl;
67 }
68 else cout<<"No"<<endl;
69 }
70 return 0;
71 }