zoukankan      html  css  js  c++  java
  • 素数个数-欧拉筛法

    模拟的时候真没想到这是一道这么麻烦的题。。。

    先来看题:

    素数个数

    题目描述

    1,2,cdots,N1,2,,N 中素数的个数。

    输入输出格式

    输入格式:

    1 个整数N

    输出格式:

    1 个整数,表示素数的个数。

     输入输出样例

    输入样例#1: 复制
    10
    输出样例#1: 复制
    4

    说明

    • 对于40% 的数据,1 N 10^6

    • 对于80% 的数据,1 lN 10^7

    • 对于100% 的数据,1 N 10^8 

    当看到这道题的时候,我直接写下了逐个取余判断的代码,然而看到数据范围的时候我就慌了。。。

    当时由于没学过关于素数筛选的算法,很显然除了打表我什么也干不了。。。

    好吧,不废话了,直接步入正题:

    由于这道题的数据范围较大,因此枚举肯定是行不通的,就算是使用正常筛法,面对10的八次方的数据也是显得十分的吃力,由此,我们要引入欧拉筛法(这里先介绍一下朴素筛法):

    由于任何合数都可以拆分成若干素数的乘积,因此每当我们找到一个素数的时候,就可以将部分合数筛选出来,那么我们就解决的部分的问题。

    并且讲到这里有一个隐含条件:就是没有被筛选出来的数就是素数(这个可以简化代码长度,也是理解这道题的关键),至于证明,我们可以用反证法:如果它不是素数,那么它一定是合数,而合数又可以拆分成两个素数的乘积,那么在找到它的因子的时候就一定会将其筛选出来。 证完

    强忍着没有在证明的时候说显然。。。

    但是,可能大家在证明的时候会发现一个问题:就是一个合数一次拆分时的素数因子可能不止一个,那么不就重复计算了吗?

    因此我们要优化!!!(由此诞生了欧拉筛法)

    由于下面讲解问题,我们先看代码:

     1 #include<cstdio>
     2 #include<cmath>
     3 int prime[100000005];
     4 bool vis[100000005];
     5 int Prime(int n)
     6 {
     7     int ans=0;
     8     for(int i=2; i<=n; i++)
     9     {
    10         if(!vis[i])
    11             prime[ans++]=i;
    12         for(int j=0; j<ans&&i*prime[j]<=n; j++)
    13         {
    14             vis[i*prime[j]]=1;
    15             if(i%prime[j]==0)
    16                 break;
    17         }
    18     }
    19     return ans;
    20 }
    21 int main()
    22 {
    23     int n;
    24     scanf("%d",&n);
    25     printf("%d",Prime(n));
    26     return 0;
    27 }

    其实也很好理解:由于合数可以拆分成不同素数*k(k∈Z),那么当我们筛选时只要筛选出最小素数因子即可,比如12

    12=4*3=6*2 很显然,我们需要的就是用素数2来筛选掉12,那么怎么实现呢?

    其实这其中有一个规律:由于i是由小到大枚举的,并且数组中的素数也是由小到大枚举的,那么显然我们会先看到4*3,又因为4在和素数2筛掉8时发现竟然能被整除,并且接下来的4*3是没有意义的计算,那么每当i%素数==0是跳出即可。

    如果你要问我具体该如何证明那我可以简单说一下:

    由于p[j]*k(k∈Z)=i,那么a[j+1]*i=a[j]*k*a[j+1],所以a[j]乘以某个数一定在将来会把这个合数筛掉,由于a[j]比a[j+1]小,那么a[j]才可能是最小素数因子。

    好的,我讲完了(好长啊qwq)

  • 相关阅读:
    springboot + mybatis + 多数据源
    Git 常见问题汇总
    Git 常见问题汇总
    sqlserver存储过程实现多表分页
    bzoj5248(洛谷4363)(2018九省联考)一双木棋
    bzoj4033 [HAOI2015]树上染色
    bzoj3195 [Jxoi2012]奇怪的道路
    bzoj1426(洛谷4550)收集邮票
    bzoj4806 炮
    bzoj1090(SCOI2003)字符串折叠
  • 原文地址:https://www.cnblogs.com/yufenglin/p/10124087.html
Copyright © 2011-2022 走看看