【深搜】选数

9、选数 (num.pas)

[问题描述]:
  已知 n 个整数 x1,x2,…,xn,以及一个整数 kkn)。从 n个整数中任选 k 个整数相加,可分别得到一系列的和。例如当 n=4k34个整数分别为 371219时,可得全部的组合与它们的和为:
    3712=22  371929  7121938  3121934
  现在,要求你计算出和为素数共有多少种。
  例如上例,只有一种的和为素数:371929)。

[输入](num.in)
  键盘输入,格式为:
  n , k 1<=n<=20kn
  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);
}



你可能感兴趣的:(【深搜】选数)