题目描述
已知 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)。
输入输出格式
输入格式:
键盘输入,格式为:
n , k (1<=n<=20,k<n)
x1,x2,…,xn (1<=xi<=5000000)
输出格式:
屏幕输出,格式为:
一个整数(满足条件的种数)。
输入输出样例
输入样例#1: 复制
4 3 3 7 12 19
输出样例#1: 复制
1
本人理解:这题需要从n个数选出k个数,即数学中的选数问题,可借助用递归实现全排列的思想来做这个题;
以下是代码:
#include<bits/stdc++.h>
using namespace std;
int s[200005],num[200005],w[200005],win[200005],lose[200005];//num【】编号
bool cmp(int x,int y)//对s[]进行排序,但实际不改变s[],仅对其对应的编号改变,并能实现但是s【x】==a【y】编号小的在前 面。
{
return s[x]==s[y]?x<y:s[x]>s[y];
}
void msort()//归并排序
{
int i=1,j=1;
num[0]=0;//存贮已处理好的人数,实现num【】的变化
while(i<=win[0]&&j<=lose[0])//归并开始
{
if(cmp(win[i],lose[j]))//判断win【i】和lose【i】的大小,谁大谁存储到num【】中,并实现s【i】==s【j】编号小的在前面。
{
num[0]++;
num[num[0]]=win[i];
i++;
}
else
{
num[0]++;
num[num[0]]=lose[j];
j++;
}
}
while(i<=win[0])//其中一个数组存储完了,同时另一个数组剩下的人分数全部小于num中的分数,并且剩下的数是有序的,只需接到num后面即可
{
num[0]++;
num[num[0]]=win[i];
i++;
}
while(j<=lose[0])
{
num[0]++;
num[num[0]]=lose[j];
j++;
}
}
int main()
{
int n,q,r,i,j;
cin>>n>>r>>q;
for(i=1;i<=2*n;i++)
{
num[i]=i;
cin>>s[i];
}
for(i=1;i<=2*n;i++)
cin>>w[i];
sort(num+1,num+2*n+1,cmp);//快排一遍
for(i=1;i<=r;i++)
{
win[0]=0;//【0】记录人数,充当数组下标
lose[0]=0;
for(j=1;j<=2*n;j+=2)
{
win[0]++;//每局比赛都有输赢
lose[0]++;
if(w[num[j]]>w[num[j+1]])//输赢的人分别放入各自数组,并s实现加分
{
s[num[j]]++;
win[win[0]]=num[j];
lose[lose[0]]=num[j+1];
}
else
{
s[num[j+1]]++;
win[win[0]]=num[j+1];
lose[lose[0]]=num[j];
}
}
msort();
}
cout<<num[q];
return 0;
}