P1036 — —选数

P1036 选数

题意:简单来说就是给定n个数,从中选k个数字作为组合,判断所有这样组合的和并判断是否是素数,输出有多少个组合和是素数,输出个数。

方法一:

暴力递归+组合数筛选

我这样的暴力递归,是会重复Ak\k次,只需要除掉这么多次即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#define MOD 998244353
using namespace std;
typedef long long LL;

int arr[100];
bool isPrime(int num)
{/*不在6的倍数两侧的一定不是质数*/
if(num==2||num==3)
 return 1;
/*不在6的倍数两侧的一定不是质数*/
if(num%6!=1&&num%6!=5)
 return 0;
 int tmp=sqrt(num);
/*在6的倍数两侧的也可能不是质数*/
 for(int i=5;i<=tmp;i+=6)
if(num%i==0||num%(i+2)==0) 
 return 0;
/*排除所有,剩余的是质数*/
 return 1;
}
bool flag[100];
int bns=0;

int ans=0;

int f(int n,int k,int s)
{
     if(k==0)
     {
 		if(isPrime(s))
 		{
         	ans++;
//		 	cout<<s;
        }
//	    cout<<s<<endl;
 	 }
     for(int i=1;i<=n;i++)
     {
     	if(!flag[i])
     	{
     		flag[i]=1;
         	f(n,k-1,s+arr[i]);
         	flag[i]=0;
        }
     }
}



int F=1;

int main()
{
     memset(flag,0,sizeof(flag));
     int n,k;
     cin>>n>>k;
     for(int i=2;i<=k;i++)
     {
     	F*=i;
     }
     for(int i=1;i<=n;i++)
     cin>>arr[i]; 
     f(n,k,0);
     cout<<ans/F<<endl; 
}

这个方法虽然是对的,但是重复了Ak\k次,时间为300ms。

方法二:

这个方法也是暴力递归,但是递归的过程中,按顺序选取,这样能保证不会重复。

节省了很多时间,为17ms.

#include<iostream>
#include<math.h>
using namespace std;
int x[20],n,k;//依照题目所设
bool isprime(int num)
{/*不在6的倍数两侧的一定不是质数*/
if(num==2||num==3)
 return 1;
/*不在6的倍数两侧的一定不是质数*/
if(num%6!=1&&num%6!=5)
 return 0;
 int tmp=sqrt(num);
/*在6的倍数两侧的也可能不是质数*/
 for(int i=5;i<=tmp;i+=6)
if(num%i==0||num%(i+2)==0) 
 return 0;
/*排除所有,剩余的是质数*/
 return 1;
}
int rule(int choose_left_num,int already_sum,int start,int end){//choose_left_num为剩余的k,already_sum为前面累加的和,start和end为全组合剩下数字的选取范围;调用递归生成全组合,在过程中逐渐把K个数相加,当选取的数个数为0时,直接返回前面的累加和是否为质数即可
    if(choose_left_num==0)return isprime(already_sum);
    int sum=0;
    for(int i=start;i<=end;i++){
        sum+=rule(choose_left_num-1,already_sum+x[i],i+1,end);
    }
    return sum;
}
int main(){
    cin>>n>>k;
    for(int i =0;i<n;i++)cin>>x[i];
    cout<<rule(k,0,0,n-1);//调用递归解决问题
}

猜你喜欢

转载自blog.csdn.net/mxYlulu/article/details/82106948
今日推荐