洛谷------P1036 [NOIP2002 普及组] 选数
Posted 大忽悠爱忽悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷------P1036 [NOIP2002 普及组] 选数相关的知识,希望对你有一定的参考价值。
选数集体集合
回溯思想解题
思路:
这里是任选三个数相加,求所有和中的素数个数。
这里可以把问题转化一下,变为:求解出从n个数中任意选k个数构成的所有组合(组合不看元素之间的顺序,与排列区分开来
),而我们这里只需要在找到一种组合时,计算当前组合的和,看是否等于素数,额外用一个变量sum,记录和为素数的个数,如果当前和为素数,那么sum++;
建议大家可以先看一下用回溯法求解组合问题,再回头来看此题,会发现其实很简单:
leetcode 39. 组合总和—回溯篇2
leetcode 40. 组合总和 II—回溯篇3
图解:
其实从上图中,我们就可以看出存在能够优化的地方:
那么如何判断当前元素到达末尾的元素个数够不够组成k个呢?
这里我们首先获取当前的结果数组中的元素个数size,用k-size来获得当前剩余需要的元素个数num,然后用可选数组的大小减去index获得当前最多可以选择的数字,然后与num进行比较 ,如果比num小,说明不满足条件,结束当前循环
代码;
#include<iostream>
using namespace std;
#include<bits/stdc++.h>
class Solution {
vector<int> num;
int sum = 0;
//判断一个数是否为质数
bool isPrime(int num)
{
if (num <= 3) {
return num > 1;
}
// 不在6的倍数两侧的一定不是质数
if (num % 6 != 1 && num % 6 != 5) {
return false;
}
int Sqrt =sqrt(num);
for (int i = 5; i <= Sqrt; i += 6) {
if (num % i == 0 || num % (i + 2) == 0) {
return false;
}
}
return true;
}
public:
int solution(vector<int>& v,int k,int index)
{
if (k==0)
return isPrime(accumulate(num.begin(), num.end(), 0))?++sum:sum;
int nums = k - num.size();//剩余需要选择的数字个数
int selNum = v.size() - index-1;//当前剩余最多可选的数字个数
for (int i = index; i < v.size()&&selNum>=nums; i++)
{
num.push_back(v[i]);
solution(v, k-1, i + 1);
num.pop_back();
}
return sum;
}
};
int main()
{
Solution s;
vector<int> v;
int n, k;
cin >> n >> k;
for (int i = 0; i < n; i++)
{
int val;
cin >> val;
v.push_back(val);
}
cout << s.solution(v, k, 0) << endl;
return 0;
}
以上是关于洛谷------P1036 [NOIP2002 普及组] 选数的主要内容,如果未能解决你的问题,请参考以下文章