题目
题意翻译
$$ 仓鼠 Dima\textsf{Dima}Dima 把一颗二叉排序树的所有边都吃掉了!!不仅如此,这棵树的所有顶点都被这只珂爱的仓鼠搞乱了。 不过他还是知道这棵树的一些性质……那就是任意两个直接相连的点之间的权值最大公约数不是 11 。为了不让打造这棵树的 \textsf{Andrew}Andrew 生气,还请你帮帮 \textsf{Dima}Dima :若可以按上述性质修复这颗二叉排序树,输出Yes;否则输出No。 树上点数 2 \leq n \leq 7002≤n≤700 ;点权 2 \leq a_i \leq 10^92≤a
i
≤10
9
题目描述
Dima the hamster enjoys nibbling different things: cages, sticks, bad problemsetters and even trees!
Recently he found a binary search tree and instinctively nibbled all of its edges, hence messing up the vertices. Dima knows that if Andrew, who has been thoroughly assembling the tree for a long time, comes home and sees his creation demolished, he’ll get extremely upset.
To not let that happen, Dima has to recover the binary search tree. Luckily, he noticed that any two vertices connected by a direct edge had their greatest common divisor value exceed 1 1 .
Help Dima construct such a binary search tree or determine that it’s impossible. The definition and properties of a binary search tree can be found here.
输入输出格式
输入格式:
The first line contains the number of vertices n n ( 2 \le n \le 700 2≤n≤700 ).
The second line features n n distinct integers a_i a
i
( 2 \le a_i \le 10^9 2≤a
i
≤10
9
) — the values of vertices in ascending order.
输出格式:
If it is possible to reassemble the binary search tree, such that the greatest common divisor of any two vertices connected by the edge is greater than 1 1 , print “Yes” (quotes for clarity).
Otherwise, print “No” (quotes for clarity).
输入输出样例
输入样例#1: 复制
6
3 6 9 18 36 108
输出样例#1: 复制
Yes
输入样例#2: 复制
2
7 17
输出样例#2: 复制
No
输入样例#3: 复制
9
4 8 10 12 15 18 33 44 81
输出样例#3: 复制
Yes
说明
The picture below illustrates one of the possible trees for the first example.
The picture below illustrates one of the possible trees for the third example.
思路
设计一个check(l,r,root)表示当前子树的根为root时,是否能用l~r之间的数构造出一个满足题意的子树。
实现很简单,就是暴力枚举l~r之间那一个数作儿子,再递归判断即可。
然而这样太暴力了,随随便便都能卡到TLE。
但是我们发现,实际上我们在搜索的过程中有大量重复搜索的地方,于是我们加上一个记忆化。
然后我们发现开700的三维数组会MLE。
由于这个数组只用存储bool值,那我们就把它开成bitset。
接着这个做法就过了。
代码
#include<bits/stdc++.h>
using namespace std;
int n,a[701];
bitset<701> vis2[701][701],ans[701][701];
bool ok[701][701];
int check(int l,int r,int root)
{
if(r<l)return true;
if(l==r)return ok[l][root];
if(vis2[l][r][root])return ans[l][r][root];
for(int i=l;i<=r;++i)
if(ok[i][root] &&check(l,i-1,i) && check(i+1,r,i))
{
vis2[l][r][root]=1;
ans[l][r][root]=1;
return true;
}
vis2[l][r][root]=2;
return false;
}
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=1;j<=n;++j)
ok[i][j]=__gcd(a[i],a[j])!=1;
ok[0][i]=true;
ok[i][0]=true;
}
if(check(1,n,0))puts("Yes");else puts("No");
}