P1036 [NOIP2002 普及组] 选数

题目描述

输入格式

输出格式

输出一个整数,表示种类数。

输入输出样例

输入 #1                                                             

4 3
3 7 12 19

输出 #1

1

3  2  1  开始

解析

它实现是从给定的一个整数序列中选择 k 个不同的数相加,使得它们的和为质数,并统计所有这样的组合
共有多少种。

为了实现这个功能,程序定义了两个主要函数:`isprime` 和 `dfs`

- `isprime` 函数用于检测一个正整数是否为质数。其工作原理是遍历从 2 到 sqrt(num) 的所有整数
检查 num 是否可以被这些数中的任何一个整除。如果 num 能被其中任何数整除,则该函数返回 0 表示 num 
不是质数;否则,当循环结束后返回 1 表示 num 是质数

- `dfs` 函数是一个深度优先搜索算法,用于递归地生成所有可能的 k 个数的组合,并计算这些数的和
在每次递归调用中,它都会增加当前组合中的数的数量(step),并将当前数加入到总和(sum)中
当 step 达到 k+1 时,说明已经找到了一组包含 k 个数的组合
此时会使用 `isprime` 函数来判断这组数的和是否为质数
如果是质数,则将全局变量 ans 增加 1,表示找到了一种符合条件的组合
然后,通过改变下一次递归调用的参数,`dfs` 函数会尝试添加序列中下一个不同的数
直到穷举完所有的可能组合(⭐️)

主函数 `main` 首先读取输入数据:整数序列的长度 n 以及需要选择的数的数量 k。
接着,读取整个整数序列并存储在数组 x 中。然后,调用 `dfs` 函数开始搜索所有可能的组合。
最后输出 ans 变量的值,即满足条件的组合总数。

哇,真神奇,上代码

#include<bits/stdc++.h>
using namespace std;
int n,x[25],k,ans=0;
int isprime(int num){
	for(int j=2;j*j<=num;j++){
		if(num%j==0){
			return 0;
		}
	}
	return 1; 
}
void dfs(int step,int f,int sum){
	if(step==k+1){
		if(isprime(sum)==1){
			ans++;
		}
		return;
	}
	for(int i=f+1;i<=n;i++){
		dfs(step+1,i,sum+x[i]);
	}
}
int main(){
	int i,j;
	cin>>n>>k;
	for(i=1;i<=n;i++){
		cin>>x[i];
	}
	dfs(1,0,0);
	cout<<ans;
	return 0;
}

1 2 3      分析

它实现的功能是:给定一个整数序列和一个正整数`k`,
找出所有由`k`个元素组成的子集,使得这些子集的和为质数,
并统计这样的子集共有多少个。

- 函数`int isprime(int num)`:判断一个数是否为质数。它通过试除法来判断,如果该数可以被小于或等于其平方根的任何数整除,则不是质数,返回0;否则是质数,返回1。
- 函数`void dfs(int step,int f,int sum)`:
这是一个深度优先搜索(DFS)函数,
用于递归地生成所有可能的子集组合,
并检查它们的和是否为质数。
参数`step`表示当前生成到第几个数,
`f`表示下一个数的起始位置,`sum`表示当前子集的和。
- `int main()`:主函数,首先读入序列长度`n`和子集大小`k`,接着读入整个序列,然后调用`dfs`函数开始搜索,并输出满足条件的子集总数。

总的来说,这段程序使用了回溯算法来枚举所有可能的子集组合,并利用`isprime`函数检查每个组合的和是否为质数,从而统计出符合条件的子集数量。

CCF要来了,加加油!!

🥹

the   end   新手上路悠~~~~~~~~~~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值