zoukankan      html  css  js  c++  java
  • wenbao与筛法素数及判断模板

     1 #define ll long long 
     2 const int maxn = 1000000;
     3 int vis[maxn],prime[maxn];
     4 void isprime()
     5 {   
     6     memset(vis,0,sizeof(vis));
     7     ll cot=0,i,j;
     8     for( i=2;i<=1000000;i++)
     9     {
    10         if(!vis[i])
    11         {
    12             prime[cot++]=i;
    13             for( j=i*i;j<1000000;j+=i)
    14             vis[j]=1;
    15         }
    16     }
    17 }

     判断模板

     1 bool prime(int x)
     2 {
     3     if(x==2)
     4         return true;
     5     if(x%2==0||x==1)
     6         return false;
     7     bool flag=true;
     8     int t=(int )sqrt((double)x);
     9     for(int i=3; i<=t; i+=2)
    10         if(x%i==0)
    11         {
    12             flag=false;
    13             break;
    14         }
    15     return flag;
    16 }

    http://blog.csdn.net/lerenceray/article/details/12420725

     1 #include<cstring>
     2 #include<iostream>
     3 #include<ctime>
     4 using namespace std;
     5 #define N 100000005
     6 
     7 bool vis[N];
     8 int p[N], cnt, phi[N];
     9 
    10 int Euler(int n){
    11     int i, j, k;
    12     phi[1] = 1;
    13     for (i = 2; i < n; ++i){
    14         if (!vis[i]){
    15             p[cnt++] = i;
    16             phi[i] = i - 1;
    17         }
    18         for (j = 0; j < cnt && i * p[j] < n; ++j){
    19             vis[i * p[j]] = true;
    20             if (i % p[j]) phi[i * p[j]] = phi[i] * phi[p[j]];
    21             else {
    22                 phi[i * p[j]] = phi[i] * p[j];
    23                 break;
    24             }
    25         }
    26     }
    27     return cnt;
    28 }
    29 
    30 int Eratosthenes (int n){
    31         int i, j, k;
    32         phi[1] = 1;
    33         for (i = 2; i < n; ++i){
    34                 if (!vis[i]) p[cnt++] = i;
    35                 for (j = i; j < n; j += i) {
    36                         if (!phi[j]) phi[j] = j;
    37                         phi[j] = phi[j] / i * (i - 1);
    38                         vis[j] = true;
    39                 }
    40         }
    41         return cnt;
    42 }
    43 
    44 int main(){
    45         clock_t st, en;
    46         int num;
    47         double sec;
    48         for (int t = 10; t < N; t *= 10){
    49                 cout << t << ':' << endl;
    50                 st = clock();
    51                 num = Euler(t);
    52                 en = clock();
    53                 sec = (double)(en - st) / (double) CLOCKS_PER_SEC;
    54                 //cout << "Euler : " << cnt << ' ' << sec << endl;
    55                 printf("Euler :		%8d	%.8lf
    ", num, sec);
    56                 memset(vis, 0, sizeof(vis)), memset(p, 0, sizeof(p)), memset(phi, 0, sizeof(phi)), cnt = 0;
    57                 st = clock();
    58                 num = Eratosthenes(t);
    59                 en = clock();
    60                 sec = (double)(en - st) / (double) CLOCKS_PER_SEC;
    61                 //cout << "Eratosthenes : " << cnt << ' ' << sec << endl;
    62                 printf("Eratosthenes :	%8d	%.8lf
    ", num, sec);
    63         }
    64         return 0;
    65 }

    http://www.bubuko.com/infodetail-837565.html

    我们先来看一下最经典的埃拉特斯特尼筛法。时间复杂度为O(n loglog n)

     1 int ans[MAXN];
     2 void Prime(int n)
     3 {
     4     int cnt=0;
     5     memset(prime,1,sizeof(prime));
     6     prime[0]=prime[1]=0;
     7     for(int i=2;i<n;i++)
     8     {
     9         if(vis[i])
    10         {
    11            ans[cnt++]=i;//保存素数 
    12            for(int j=i*i;j<n;j+=i)//i*i开始进行了稍微的优化
    13            prime[j]=0;//不是素数 
    14         }
    15     }
    16     return ;
    17 }

    显然,当一个数是素数的时候,那么他的倍数肯定是合数,筛选标记即可。从i*i而不从i*2开始,是因为已经i*3,i*2早已经被2,3筛过了。

    由此,我们也可以发现有的合数被重复筛除,例如30,2*15筛了一次,5*6重复筛除,所以也就有了我们下面要提到的欧拉线性筛法。

    不会重复筛除,是线性O(n)的复杂度。

     1 const int MAXN=3000001;
     2 int prime[MAXN];//保存素数 
     3 bool vis[MAXN];//初始化 
     4 void Prime(int n)
     5 {
     6     int cnt=0;
     7     memset(vis,0,sizeof(vis));
     8     for(int i=2;i<n;i++)
     9     {
    10         if(!vis[i])
    11         prime[cnt++]=i;
    12         for(int j=0;j<cnt&&i*prime[j]<n;j++)
    13         {
    14             vis[i*prime[j]]=1;
    15             if(i%prime[j]==0)//关键 
    16             break;
    17         }
    18     }
    19     return cnt;//返回小于n的素数的个数 
    20 }
     1 void prime(){
     2     a[0] = a[1] = 1;
     3     for(int i = 2; i < maxn; i++){
     4         if(!a[i]){
     5             b[num] = i, num++;
     6         }
     7         for(int j = 0; j < num && i*b[j] < maxn; j++){
     8             a[i*b[j]] = 1;
     9             if(i%b[j] == 0) break;
    10         }
    11     }
    12 }

    只有不断学习才能进步!

  • 相关阅读:
    win10操作技巧介绍,很实用!
    信息时代与人工智能时代的教育变革
    《此生未完成》痛句摘抄(3)
    《下辈子还教书》经典语录(1)
    《给教师的阅读建议》经典语录
    《此生未完成》痛句摘抄(4)
    记录程序人生2020.8.11
    最全、最详细的配置jdk十步法!
    《此生未完成》痛句摘录(2)
    “温室里的花朵”也要直面困难
  • 原文地址:https://www.cnblogs.com/wenbao/p/5733527.html
Copyright © 2011-2022 走看看