P1036 [NOIP 2002 普及组] 选数(dfs+素数筛选)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e8+5;
vector<bool> is(N, true); // 使用 bool,初始化全 true
void f() {// 埃氏筛法,预处理 0 到 N-1 的素数表
is[0] = is[1] = false; // 非素数
for (int i = 2; i * i < N; i++) {
if (is[i]) {
for (int j = i * i; j < N; j += i) {
is[j] = false;
}
}
}
}
int n,k;
ll x[25];
vector<ll> comb;
int ans=0;
void dfs(int pos,int cnt){
if(cnt==k){ // 终止条件:已选 k 个数
ll sum=0; // 计算当前组合的和
for(int i=0;i<k;i++){
sum+=comb[i];
}
if(is[sum]) ans++;
return;
}
if(pos>=n || n-pos+cnt<k) // 剪枝:位置超界或剩余数不足
return;
comb.push_back(x[pos]);// 选择当前数 x[pos],加入组合
dfs(pos+1,cnt+1); // 递归:位置加 1,计数加 1
comb.pop_back(); // 回溯:撤销选择
dfs(pos+1,cnt); // 不选当前数,递归下一位置
}
int main(){
f();
cin>>n>>k;
for(int i=0;i<n;i++){
cin>>x[i];
}
dfs(0,0); // 从位置 0 开始,选 0 个数,开始回溯
cout<<ans;
return 0;
}
dfs
- pos :当前考虑的数组位置。
- cnt :已选择的数量。
剪枝 :
pos>=n:超出数组范围。
n−pos+cnt<k:剩余元素不足以选到 k 个,返回。