• 欧拉筛+埃式筛求素数


    参考:https://blog.csdn.net/nk_test/article/details/46242401

    先看一下经典的埃拉特斯特尼筛法:

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

    时间复杂度为O(nloglogn),原理很简单,一个素数的倍数一定是合数,删除即可。从i×i开始而不从2×i开始是因为2×i早被2的倍数筛选过了。但埃式筛法的缺点是有些数会被重复筛选,比如30会被2×15和5×6筛选。

    下面介绍欧拉筛,首先我们知道任何数都能被一些素数的乘积表示,假设我们令每个合数只被它的最小素因数筛去,那么就是线性时间,算法复杂度降到了O(n)。先看代码:

     1 const int MAXN=3000001;
     2 int prime[MAXN];//保存素数 
     3 bool vis[MAXN];//初始化 
     4 int Prime(int n)
     5 {
     6     int cnt=0;
     7     memset(vis,1,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]]=0;
    15             if(i%prime[j]==0)//关键 
    16             break;
    17         }
    18     }
    19     return cnt;//返回小于n的素数的个数 
    20 }

    代码中体现在:if(i%prime[j]==0)break;
    prime数组中的素数是递增的,当 i 能整除 prime[j],那么 i*prime[j+1] 这个合数肯定被 prime[j] 乘以某个数筛掉。
    因为i中含有prime[j], prime[j]比 prime[j+1] 小。接下去的素数同理。所以不用筛下去了。
    另外i*prime[j-1]的最小素因子只能是prime[j-1],因为i的最小素因子是prime[j],而prime[j]>prime[j-1],所以在满足i%prime[j]==0这个条件之前以及第一次满足该条件时,prime[j]必定是prime[j]*i的最小因子。证毕。

    但是只是求素数的话欧拉筛有些没必要,除非数据很大会卡埃式筛,欧拉筛的很重要的应用是欧拉函数.

  • 相关阅读:
    node.js_1
    CSS实现垂直居中的方法
    Javascript实现图片的预加载的完整实现------》转载自(空城计-Code记)
    面向对象----选项卡
    for循环执行步骤
    适配器模式 在Android中的简单理解
    单例模式
    Android的ImageLoader图片加载简单逻辑
    在魅族手机上使用ObjectAnimator竟然不兼容?原来是这样……
    Android异步消息处理机制,Handler,Message,Looper的简单理解
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10490614.html
Copyright © 2020-2023  润新知