zoukankan      html  css  js  c++  java
  • P1036 选数

    https://www.luogu.com.cn/problem/P1036

    方法一:递归回溯+素数判断

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n, k, ans=0;
     4 int x[25], a[25];
     5 bool vis[25];
     6 bool is_prime(int p){
     7     if(p<2)return 0;
     8     for(int i=2; i<=sqrt(p); i++)
     9         if(p%i==0)return 0;
    10     return 1;
    11 }
    12 void dfs(int step)
    13 {
    14     if(step>k){
    15         int sum=0;
    16         //for(int i=1; i<=k; i++)cout<<a[i]<<" ";
    17         for(int i=1; i<=k; i++)sum+=x[a[i]];//对应序号的数值
    18         if(is_prime(sum))ans++;
    19         return;
    20     }
    21     for(int i=a[step-1]+1; i<=n; i++)
    22     {
    23         if(!vis[i])
    24         {
    25             a[step]=i;
    26             vis[i]=1;
    27             dfs(step+1);
    28             vis[i]=0;
    29         }
    30     }
    31 
    32 }
    33 int main()
    34 {
    35     
    36     cin>>n>>k;
    37     for(int i=1; i<=n; i++)
    38         cin>>x[i];
    39     dfs(1);
    40     cout<<ans;
    41     return 0;
    42 } 

    以上方法首先要熟练用递归写出“组合”,注意跟全排列的差异在21行,前提知识请查看  》全排列+组合数

    方法二:二进制枚举+素数筛

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int a[25];
     4 const int max_n=10000005;
     5 int b[max_n];
     6 void su(){//素数筛 建立表供后面查 
     7     b[1]=1;
     8     int m=sqrt(max_n);
     9     for(int i=2; i<=m; i++)
    10         if(!b[i])
    11             for(int j=2; j<=max_n/i; j++)
    12                 b[i*j]=1;
    13 //    for(int i=2; i<100; i++)
    14 //        if(!b[i])
    15 //            cout<<i<<" ";
    16 }
    17 int main()
    18 {
    19     su();
    20     int n, m, ans=0;
    21     cin>>n>>m;
    22     for(int i=0; i<n; i++)cin>>a[i];//输入
    23     for(int i=0; i<(1<<n); i++){  
    24         int sum=0;
    25         int num=0, kk=i;//num统计i中1的个数;kk用来处理i
    26         while(kk){
    27             kk=kk&(kk-1);//清除kk中的最后一个1
    28             num++;//统计1的个数
    29         }
    30         
    31         if(num==m){//二进制数中的1有k个,符合条件
    32             for(int j=0; j<n; j++)
    33                 if(i&(1<<j))
    34                     sum+=a[j];//cout<<a[j]<<" ";
    35             
    36             if(!b[sum])ans++;//判断sum是否为素数 
    37         }
    38     }
    39     cout<<ans;
    40     return 0;
    41  }

    以上方法看不懂的请参考笔者之前写过的一篇博客》》重写--全排列--全面理解搜索

    方法三:递归(摘自洛谷题解)

     1 #include <iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 
     5 bool isprime(int a){//判断素数
     6     /*0和1特判真的没啥用对这题
     7     吐槽:题中n的数据范围很奇怪,
     8     n还有可能=1.....那k<n......
     9     */
    10     for(int i = 2;i * i <= a; i++)//不想用sqrt,还要头文件
    11         if(a % i == 0)//如果整除
    12             return false;//扔回false
    13     //程序都到这里的话就说明此为素数
    14     //否则就被扔回了
    15     return true;//扔回true
    16 }
    17 
    18 int n,k;
    19 int a[25];
    20 long long ans;
    21 
    22 void dfs(int m, int sum, int startx){//最重要的递归
    23 //m代表现在选择了多少个数
    24 //sum表示当前的和
    25 //startx表示升序排列,以免算重
    26     if(m == k){//如果选完了的话
    27         if(isprime(sum))//如果和是素数
    28             ans++;//ans加一
    29         return ;
    30     }
    31     for(int i = startx; i < n; i++)
    32         dfs(m + 1, sum + a[i], i + 1);//递归
    33         //步数要加一,和也要加
    34         //升序起始值要变成i+1,以免算重
    35     return ;//这一个步骤下,所有的都枚举完了
    36     //直接返回去
    37 }
    38 
    39 int main(){
    40     scanf("%d%d",&n,&k);//输入
    41     
    42     for(int i = 0; i < n; i++)
    43         scanf("%d",&a[i]);//循环读入
    44     dfs(0,0,0);//调用函数
    45     printf("%d
    ",ans);//输出答案
    46     return 0;//结束程序
    47 }
  • 相关阅读:
    巴比伦富翁的理财课:有史以来最完美的致富圣经读后感
    【数据结构与算法】爱吃香蕉的珂珂:二分法思想实现
    【数据结构与算法】有序数组查找:二分查找算法实现
    【数据结构与算法】找出最小的k个数:三路快速排序算法思想实现
    【数据结构与算法】第K大的元素:三路快速排序算法思路
    【数据结构与算法】颜色分类:三路快速排序算法思想实现
    页面轮播
    sh重启脚本
    关于mac自带的openssl和brew安装的openssl冲突
    vconsole使用
  • 原文地址:https://www.cnblogs.com/tflsnoi/p/13303061.html
Copyright © 2011-2022 走看看