Problem C: 递归入门组合+判断素数
Posted heyour
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Problem C: 递归入门组合+判断素数相关的知识,希望对你有一定的参考价值。
Description
已知 n 个整数b1,b2,…,bn
以及一个整数 k(k<n)。
从 n 个整数中任选 k 个整数相加,可分别得到一系列的和。
例如当 n=4,k=3,4 个整数分别为 3,7,12,19 时,可得全部的组合与它们的和为:
3+7+12=22 3+7+19=29 7+12+19=38 3+12+19=34。
现在,要求你计算出和为素数共有多少种。
例如上例,只有一种的和为素数:3+7+19=29。
Input
第一行两个整数:n , k (1<=n<=20,k<n)
第二行n个整数:x1,x2,…,xn (1<=xi<=5000000)
Output
一个整数(满足条件的方案数)。
最终AC代码:
#include <cstdio> int k, n, num, p[25], a[25]; //p[]数组保留选择的数组序号 bool vis[22]={false}; bool isPrime(int n){ if(n < 2) return false; for(int i=2; i*i<=n; i++) if(n%i == 0) return false; return true; } void DFS(int index){ if(index == k+1){ int i, sum=0; for(i=1; i<=k; i++) sum += a[p[i]]; if(isPrime(sum)) num++; return ; } for(int i=index; i<=n; i++){ if(!vis[i] && p[index-1]<i){ p[index] = i; vis[i] = true; DFS(index+1); vis[i] = false; } } } int main(){ int i; p[0] = 0; while(~scanf("%d %d", &n, &k)){ for(i=1; i<=n; i++) scanf("%d", &a[i]); num = 0; DFS(1); printf("%d ", num); } return 0; }
总结:在最开始写代码时,担心大数据时会超时,所以采用map记录已经判断过的sum,但是后来测试发现,当sum一样,组成sum的元素不同时,这里视为两种情况。其次,当使用如下形式 int a=sqrt(b); 那么得到的a的值将为0 正确做法是 int a=(int)sqrt(b);
后来百度,看到一种更妙的解法(虽然我承认这个解法见过好多次,但是为什么每次自己想不起来呢?)
自己后来跟着这个思路写了一遍,如下:
#include <cstdio> int n, k, num, a[25]; bool isPrime(int n){ if(n < 2) return false; for(int i=2; i*i<=n; i++) if(n%i == 0) return false; return true; } void DFS(int index, int cnt, int sum){ if(cnt == k){ //说明得到了k个数 if(isPrime(sum)) num++; return ; } if(index==n || cnt>k) return ; //说明超过判断范围了 DFS(index+1, cnt+1, sum+a[index]); //选择index DFS(index+1, cnt, sum); //不选择index } int main(){ int i; while(~scanf("%d %d", &n, &k)){ for(i=0; i<n; i++) scanf("%d", &a[i]); num = 0; DFS(0, 0, 0); printf("%d ", num); } return 0; }
嗯,很简单,而且速度快了很多.........
以上是关于Problem C: 递归入门组合+判断素数的主要内容,如果未能解决你的问题,请参考以下文章