洛谷P1036 选数(回溯法)

来源:互联网 发布:淘宝查看同行店铺数据 编辑:程序博客网 时间:2024/04/27 21:57

洛谷P1036 选数(回溯法)

题目描述

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

解题分析

用回溯法求从1~n中取k个不同数的不同组合,然后求以这些组合为下标的k个数之和,判断其是否为素数。可以利用测试法判断某个数是否为素数。

#include #include #include #include #include #include #include #include using namespace std;#define N 22int n, k, x[N], y[N], used[N], ans = 0;void get_i(int &x) {    char ch = getchar();    x = 0;    while(!isdigit(ch)) ch = getchar();    while(isdigit(ch)) {        x = x * 10 + ch - '0';        ch = getchar();    }}// 快速幂int qmod(int a, int x1, int x) {    long long tmp;    if(x1==1)        return a;    else if(x1==0)        return 1;    tmp = qmod(a, x1>>1, x);    if(x1&1)        return ((tmp * a) % x * tmp) % x;    return (tmp * tmp) % x;}// 测试法判定x是否为素数int isPrime(int x) {    int a, t = 4;    srand(time(NULL));    while(t--) {        a = rand() % (x - 1) + 1;        if(qmod(a, x-1, x)!=1)            return 0;    }    return 1;}int judge() {    int i, tmp = 0;    for(i=1; i<=k; i++)        tmp += x[y[i]];    return isPrime(tmp);}void dfs(int m) {    int i;    if(m==k+1) {// 得到一个组合        ans += judge();        return;    }    for(i=y[m-1]; i<=n; i++) {        if(!used[i]) {            y[m] = i;            used[i] = 1;            dfs(m+1);            used[i] = 0;        }    }}int main() {    ios::sync_with_stdio(false);    int i;    get_i(n), get_i(k);    for(i=1; i<=n; i++)        get_i(x[i]);    y[0] = 1;    dfs(1);    cout<