从n个数中取k个数,如何使得选取不重复?
1.可以将这个问题转化为求这k个数的严格升序(降序)列。先考虑n个数中没有重复的数,在dfs模板选下一个数时需要增加该数需比上一个数大的条件。若有重复的数,使用(值,序号)对来保证其中没有重复的数。
#include<bits/stdc++.h>
using namespace std;
int n, k;
const int N = 25;
int cnt;
int st[N];
typedef pair<int, int> pr;
pr q[N], s[N];
int is_prime(int u)
{
for(int i = 2; i <= pow(u, 0.5); i++)
if(u % i == 0) return 0;
return 1;
}
void dfs(int u)
{
if(u == k){
int sum = 0;
for(int i = 0; i < k; i ++) sum += s[i].first;
if(is_prime(sum)) cnt++;
return;
// for(int i = 0; i < k; i ++) cout << s[i].first << ' ';
// cout << endl;
// return;
}
for(int i = 0; i < n; i ++){
if(!st[i] && (u == 0 || q[i] > s[u - 1])){
st[i] = 1;
s[u] = q[i];
dfs(u + 1);
st[i] = 0;
}
}
}
int main()
{
cin >> n >> k;
for(int i = 0; i < n; i++){
int t;
cin >> t;
q[i] = {t, i};
}
dfs(0);
// int t = 1;
// for(int i = 2; i <= k; i ++) t *= i;
cout << cnt;
}
2.在dfs函数增加一个参数i,每次选数从i开始选,因此下一次选的数一定比上一个数序号更大,保证了序号的升序
这里的不需要使用st数组判定该数是否选取过,因为严格向后选取
#include<bits/stdc++.h>
using namespace std;
int n, k;
const int N = 25;
int s[N], q[N], cnt;
// int st[N];
int issu(int u)
{
for(int i = 2; i <= pow(u, 0.5); i++)
if(u % i == 0) return 0;
return 1;
}
void dfs(int u, int j)
{
if(u == k){
int sum = 0;
for(int i = 0; i < k; i ++) sum += s[i];
if(issu(sum)) cnt++;
return;
// for(int i = 0; i < k; i ++) cout << s[i] << ' ';
// cout << endl;
// return;
}
for(int i = j; i < n; i ++){
s[u] = q[i];
dfs(u + 1, i + 1);
}
}
int main()
{
cin >> n >> k;
for(int i = 0; i < n; i++) cin >> q[i];
dfs(0, 0);
// int t = 1;
// for(int i = 2; i <= k; i ++) t *= i;
cout << cnt;
}