[NOIP2002] 选数

文章讲述了如何通过C++编程解决NOIP2002竞赛中的一道题目,涉及选择k个互不相同的数,使得它们的和是一个质数。作者采用递归方法避免数据重复,并详细介绍了判断质数和递归代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

NOIP 2002 普及组 选数

题目传送门

题目大意

从一个有 n n n 个数的数列中选出 k k k 个互不相同的数 , 要使他们的和为一个质数 , 求一共有多少种选择的方法

题目分析

看到这道题的第一眼 , 我首先想到的是使用 C++ 中自带的 n e x t next next _ p e r m u t a t i o n permutation permutation 函数 , 但是试过之后发现,有的情况会被重复记录 , 造成答案偏大.这时我想到了另一种方法 : 递归.

既然使用自带的函数会因为数据重复记录造成重复 , 那么我们在写递归的时候就要注意数的排列顺序 , 也就是说 , 我们可以在输入之后对它进行排序,以达到不重复的目的

代码分析

这道题的核心代码主要是分为两部分:

判断质数

bool zhishu(int num){
	if(num==0||num==1){
		return 0;//质数特判:0和1不是质数
	}
	for(int i=2;i*i<=num;i++){
		if(num%i==0){
			return 0;//能整除,不是质数
		}
	}
	return 1;
}

判断质数是竞赛中常用的子程序之一 , 在这里不过多解释了 , 主要强调一点 , 因为一个数的因数都是成对出现的 , 可以只枚举某个数的前一半因数 , 节省时间

递归代码

void zhaoshu(int geshu,int sum,int head){
	//geshu:已经选了几个
	//sum:当前的已经选好了的数的和
	//head:下一个数的起始位置
	if(geshu==k){//数已经选够了
		if(zhishu(sum)==1){//满足题意
			ans++;//结果数+1
		}
		return;
	}else {//还不够
		for(int i=head;i<=n;i++){
			zhaoshu(geshu+1,sum+a[i],i+1);//递归:继续寻找
		}
		return;
	}
}

这里我们定义了三个变量 : g e s h u , s u m , h e a d geshu ,sum,head geshu,sum,head , 这些变量都是用来记录我们找数过程中的信息的 . 只有良好的数据记录 , 才可以确保找数的时候不会重复

还有就是递归边界的设置 , 这里因为题目要我们找的是 k k k 个数 , 所以我们就可以把边界设为 g e s h u = = k geshu==k geshu==k ,等到找够了的时候就可以进行判断了

AC Code

#include<bits/stdc++.h>
using namespace std;
int n,k;
int a[21];
int ans;
bool zhishu(int num){
	if(num==0||num==1){
		return 0;
	}
	for(int i=2;i*i<=num;i++){
		if(num%i==0){
			return 0;
		}
	}
	return 1;
}
void zhaoshu(int geshu,int sum,int head){
	if(geshu==k){
		if(zhishu(sum)==1){
			ans++;
		}
		return;
	}else {
		for(int i=head;i<=n;i++){
			zhaoshu(geshu+1,sum+a[i],i+1);
		}
		return;
	}
}
int main(){
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	sort(a+1,a+n+1);
	zhaoshu(0,0,1);
	cout<<ans;
	return 0;
}

注意一点,因为我们读入这一串数字的时候是从下标 1 1 1 开始的 , 所以一定要从 h e a d = 1 head=1 head=1 开始递归,否则会出现错误。

完结撒花~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值