[搜索] 质数
题目描述
给定
n
n
n 个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?
在满足最少的组数的情况下,使得元素个数最多的那一组的元素个数尽可能的少。
输入格式
第一行
1
1
1 个数
n
n
n。
接下来
n
n
n 行,每行
1
1
1 个数字表示
a
i
a_i
ai。
输出格式
一行两个正整数,第一个数是最少的组数,第二个数是满足最少组数的境况下,元素个数最多的那一组的元素个数。
样例
样例输入1:
6
14
20
33
117
143
175
样例输出1:
3 2
样例输入2:
4
2
4
7
9
样例输出2:
2 2
数据范围
对于
30
%
30\%
30% 的数据,
n
≤
8
n \le 8
n≤8。
对于
60
%
60\%
60% 的数据,
n
≤
10
n \le 10
n≤10。
对于
100
%
100\%
100% 的数据,
n
≤
15
,
1
≤
a
i
≤
1
0
4
n \le 15, 1 \le a_i \le 10^4
n≤15,1≤ai≤104。
题解
由于
n
n
n 的范围很小,所以可以直接爆搜。
dfs(int x, vector<int> v, int l1, int l2)
,
x
x
x 表示当前搜到的数的编号,
v
v
v 表示当前的情况,
l
1
l1
l1 表示
a
n
s
1
ans1
ans1,
l
2
l2
l2 表示
a
n
s
2
ans2
ans2。
如果
x
>
n
x > n
x>n,说明已经搜完了,更新答案。
否则继续搜索,接下来有两个情况:
- 重新开一个新的组。
- 在现在的组中,找到一个组使得每个数都与其互质,放进去。
接下来进行剪枝:
- 如果当前的已经比答案差了,直接返回。
- 还可以进行记忆化,如果搜到第 i i i 个数的答案已经不比前面搜到的更优,返回。
代码:
int a[20];
bool check(int x, int y){//判断互质
如果 gcd(x, y) 是 1,则互质返回1,否则返回0
}
//组数,每组中最大元素个数
int ans1 = 1e9, ans2 = 1e9;
void dfs(int x, vector<int> v[20], int l1, int l2){
if(l1 > ans1){
return;
}
if(l1 == ans1 && l2 >= ans2){
return;
}
if(x > n){
if(l1 < ans1){
ans1 = l1;
ans2 = l2;
}
else if(l1 == ans1){
ans2 = min(ans2, l2);
}
return;
}
vector<int> t[20];
for(int i = 1; i <= l1; ++ i){
for(auto j : v[i]){
t[i].push_back(j);
}
}
----新开一组----
t[l1 + 1].push_back(a[x]);
dfs(x + 1, t, l1 + 1, max(l2, 1));
----从已有的组中选出组放进去----
for(int i = 1; i <= l1; ++ i){
int len = 0, fl = 1;
for(auto j : v[i]){
++ len;
if(check(j, a[x]) == 0){
fl = 0;
break;
}
}
//互质
if(fl){
vector<int> t1[20];
for(int i1 = 1; i1 <= l1; ++ i1){
for(auto j1 : v[i1]){
t1[i1].push_back(j1);
}
}
t1[i].push_back(a[x]);
dfs(x + 1, t1, l1, max(l2, len + 1));
}
}
}
int main(){
输入
vector<int> v[20];
dfs(1, v, 0, 0);
输出
}