9、选数 (num.pas)
[问题描述]:
已知 n 个整数 x1,x2,…,xn,以及一个整数 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)。
[输入]:(num.in)
键盘输入,格式为:
n , k (1<=n<=20,k<n=
x1,x2,…,xn (1<=xi<=5000000)
[输出]:(num.out)
屏幕输出,格式为:
一个整数(满足条件的种数)。
[输入输出样例]:
输入:
4 3
3 7 12 19
输出:
1
【分析】由于数据较大,需要筛法求素数(筛1-10000),剩下就裸搜。。
数组开[10000]就wa了= =开[10001]就过了 不知道为什么。。c++还不熟ORZ
#include <cstdio> #include <cmath> #include <cstring> using namespace std; int n,m; long ans; long a[20]; long prime[10001]; // bool notprime[10001]={0}; int prime_num=0; long maxp=10000; void PR() { for (long i=2;i<=maxp;i++) { if (!notprime[i]) prime[prime_num++]=i; for (long j=0;j<prime_num && i*prime[j]<=maxp;j++) { notprime[i*prime[j]]=1; if (!(i%prime[j])) break; } } prime_num--; } bool check(long s) { if (s==1) return(false); if (s==2) return(true);//注意特判1和2 long b=long(sqrt(s)); for (long i=0;(i<=prime_num)&&(prime[i]<=b);i++) if(s % prime[i]==0) return(false); return(true); } void Search(long sum,int k,int c) { if (k==m) { if (check(sum)) ans++; return; } for (int i=c+1;i<n;i++) Search(sum+a[i],k+1,i); } int main() { freopen("num.in","r",stdin); freopen("num.out","w",stdout); scanf("%d%d",&n,&m); for (int i=0;i<n;i++) scanf("%ld",&a[i]); PR();//筛法求素数 Search(0,0,-1); printf("%ld\n",ans); }