xcoj1009-密码

来源:互联网 发布:妮维雅 爽肤水 知乎 编辑:程序博客网 时间:2024/06/11 05:58

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;}
1 0
原创粉丝点击