P1036 选数

题目链接:https://www.luogu.com.cn/problem/P1036

image

题目大意:
从n个整数中选出k个相加,统计所有可能的和中有多少个是素数,输出和为素数的选法数(不同选法即使和相同也分别计数)。
这个题目的所有选法恰好可以组成一棵树,我们可以用DFS深度搜索每一种可能性

我们从每个位置放什么数出发深度搜索所有可能性;
image
第 1 个位置能放的下标上界是 n−k+1 = 2,所以 12、19 不会出现在第 1 个位置;

我们定义初始数组,构建后存数据的数组,和从当前位置开始遍历的变量分别为,arr:读入数组;ans:存当前组合;start:可选下标起点。dfs 从 (1, 1) 开始
dfs 核心代码
image
然后数组按 1~n 存储,从 dfs(1, 1) 开始搜索
image
最后结果为:
image
完整代码:

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N=20;
int arr[N];
int ans[N];
int dd=0;
int n,k;

bool isPrime(int n) {
    if (n <= 1) return false;     // 0、1 不是素数
    if (n == 2) return true;      // 2 是唯一的偶素数
    if (n % 2 == 0) return false; // 排除其他偶数

    // 只检查奇数因子,且只需检查到 sqrt(n)
    for (int i = 3; i * i <= n; i += 2) {
        if (n % i == 0) return false;
    }
    return true;
}

void dfs(int x,int stare){
//x为遍历域的最小值
//stare 为当前遍历开始的位置
	if(x>k){//当遍历的位置到第四个开始统计计算
		int sum=0;
		for(int i=1;i<=k;i++){
			sum+=ans[i];
		}
		if(isPrime(sum)){//判断是否为素数
			dd++;
		}
		return ;//回溯上个支路
	}
	
	for(int i=stare;i<=n;i++){//stare初始为1
		ans[x]=arr[i];//当前x位置数值为arr[i];
		dfs(x+1,i+1);//递归进入下一个支路
		ans[x]=0;//状态恢复
	}
}

int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>arr[i];
	}
	dfs(1,1);
	cout<<dd;
}
声明:部分图片由ai生成
posted @ 2026-11-02 21:43  Dbodo  阅读(2)  评论(0)    收藏  举报