( 数论专题 )【 欧拉筛 】

( 数论专题 )【 欧拉筛 】

线性筛是一个很基础的算法,但是我一直没学。直到一次考试,因为O(n√n)会超时,用了表筛,结果被卡了代码长度,于是开始学习欧拉筛。

算法思路:

  对于每一个数(无论质数合数)x,筛掉所有小于x最小质因子的质数乘以x的数。比如对于77,它分解质因数是7*11,那么筛掉所有小于7的质数*77,筛掉2*77、3*77、5*77。

  好吧,是不是听起来太简单了。。。。没事,重点在证明。

算法证明:

  首先我们要明确证明思路。如果要证明它是对的,只要保证两点:没用重复筛、没有漏筛

  1、没有重复筛。

    我们假设一个合数分解成p1*p2*p3,并且保证p1<p2<p3。我们知道,筛掉这个合数的机会有:p1和p2*p3,p2和p1*p3,p3和p1*p2。但我们知道,我们选择的那个质数必须小于那个合数的最小质因子。比如p2和p1*p3,因为p2>p1,所以这样是筛不到的。唯一会筛的是第一种:p1和p2*p3。

  2、没有漏筛。

  还是假设把这个合数分解质因数a*b*c,保证a<b<c然后我们设s=b*c,s肯定小于刚才那个合数,说明肯定对于它已经筛过,然后a肯定小于s,因为s=b*c,并且a是最小的因子。说明a*s也就是这个合数一定筛过。

证明没看懂的直接看代码吧。。挺好背的。

#include <bits/stdc++.h>
#define int long long

using namespace std;

const int maxn = 2e6+10;
int primes[maxn],cnt;
bool isprime[maxn];

void get_prime()
{
    memset(isprime,true,sizeof(isprime));
    for ( int i=2; i<=maxn; i++ ) {
        if ( isprime[i]==true ) primes[cnt++]=i;
        for ( int j=0; j<cnt&&i*primes[j]<=maxn; j++ ) {
            isprime[ i*primes[j] ] = false;
            if ( i%primes[j]==0 ) break;
        }
    }
}

signed main()
{
    get_prime();
    for ( int i=0; i<100; i++ ) cout << primes[i] << " ";

    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值