0
点赞
收藏
分享

微信扫一扫

洛谷P1036 选数(递归)

晴儿成长记 2023-02-07 阅读 57


题目描述

已知 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;
}


举报

相关推荐

0 条评论