xcoj1009-密码

1009: 密码题目地址
时间限制: 1 Sec 内存限制: 64 MB

题目描述
小翔同学的宿舍WIFI添加了密码,密码每天都会变更。而小翔每天都会给蹭网的同学们提供密码提示。现在请你根据密码提示,编写程序破译密码。
已知密码提示给出了n个整数 a1,a2,…,an,以及一个整数 t(t小于n)。从这n个整数中任选t个相加,可分别得到一系列的和。例如当 n=4,t=3,4 个整数分别为 3,7,12,19 时,可得全部组合的和分别为:
3+7+12=22  3+7+19=29  7+12+19=38  3+12+19=34。
而和为素数的个数即为小翔宿舍WIFI的密码。
例如上例,只有一种的和为素数:3+7+19=29,于是密码即为1。
输入
n , t (1<=n<=20,t<n)
a1,a2,…,an (1<=ai<=5000000)

输出
一个整数(即为密码)。
样例输入
4 3
3 7 12 19
样例输出
1

思路:本题首先打表产生素数;然后再递归产生组合数,即n个数中选取t个数,然后将产生的组合数相加根据素数表验证是否为素数,并统计结果

#include <iostream>
#include <cstring>
#include <cmath>
#include <fstream>
using namespace std;

int prime[100005];  //素数表
int data[21];
int cnt, t;

void getPrime()  //产生素数表
{
    prime[1] = false;
    int sq = sqrt(100005+0.5);
    for(int i = 2; i <= sq; i ++)
    {
        if(!prime[i])
        {
            continue;
        }
        for(int j = i + i; j < 100005; j += i)
        {
            prime[j] = false;
        }
    }
}

void f(int c[], int t) //统计结果
{
    long sum = 0;
    for(int i = 0; i < t; i ++)
    {
        sum += c[i];
        //cout << c[i] << "  ";
    }
    //cout << sum << endl;
    if(prime[sum])
    {
        cnt ++;
    }
}

//产生组合数,arr为原始数组,n为数组的个数,c为储存组合数数组,t为选取数的个数,i为当前选取的数组的位置,num为当前剩余需要选的数字个数
void com(int arr[], int n, int c[], int t, int i, int num)
{
    if(num == 0)
    {
        f(c, t);
    }
    else
    {
        for(int j = i; j < n-num+1; j ++)
        {
            c[t-num] = arr[j];
            //cout << arr[j] << " " << c[t-num] << endl; 
            com(arr, n, c, t, j+1, num-1);
        }
    }
}

int main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    //ifstream cin("data.in");
    memset(prime, true, sizeof(prime));
    getPrime();
    int n;
    while(cin >> n)
    {
        cin >> t;
        int c[21];
        cnt = 0;
        for(int i = 0; i < n; i ++)
        {
            cin >> data[i];
            //cout << data[i] << endl;
        }
        com(data, n, c, t, 0, t);
        cout << cnt << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/topk/p/6580114.html