浅析线性筛法

今天晚上,在家里自学了一下线性筛法,还是比较容易理解的,并没有想象的那么难。


所谓线性就是O(n)的效率咯,线性筛法较快的一个本质就是他不会干重复的事,例如12——普通的筛法在素数2时候筛一次,素数3时筛一次,很明显这些是不必要的选择,我们可以舍去。


所以,在线性筛法里的优化就是,如果枚举素数倍数的数除以当前所拥有的质数的其中一个数的余数为0的时候,则可以退出了。


如果不懂上面那句话的话,可以试着看看代码是如何实现的。


代码:

var
        bZ:Array[1..1000000] of boolean;
        a:Array[0..200000] of longint;
        n,i,j:longint;
begin
        readln(n);

        for i:=2 to n do
        begin
                if not bz[i] then
                begin
                        inc(a[0]);
                        a[a[0]]:=i;
                end;
                for j:=1 to a[0] do
                begin
                        if a[j]*i>n then break;
                        bz[i*a[j]]:=true;
                        if i mod a[j]=0 then break;
                end;
        end;

        for i:=1 to a[0] do
                 write(a[i],' ');
end.


现在讲讲这种优化的本质。


例如当前筛掉是4的倍数时(x=4),拥有的素数为2,3,那么,我们之前已经讲过,3*4这个数我们无需筛,所以,我们只要判断 x mod 枚举的素数 的答案是否为0,如果为0,则可以直接break,如何证明呢?


设当前枚举的第i个素数所乘的倍数为x,而当前枚举的第i个素数为p,

则如果i mod p=0,则代表i是p的倍数,则如果i不管再乘以什么数,依然是p的倍数.

由此可知,当x*3,x*5,x*7……这些其实都可以被x*2来筛,所以,当i mod p=的时候,接下来所需筛的数就毫无意义了,也就无需筛了,也就可以Break了。


没错,就是这么easy.




但是在此方法下我拓展一个知识点,名为:欧拉函数.


用上面的筛数方法,在线性时间内求出n以内所有的素数,以及n以内所有的欧拉函数.


首先需明白的是,何为欧拉函数。————欧拉函数也就是n以内,所有与n互质的数的数目。

例如n=8,则欧拉函数有:1,3,5,7


求欧拉函数的方法很多,最容易想到的当然就是暴力,用gcd函数判断欧拉函数,时间复杂度为O(n*logn)(网上有gcd函数的时间复杂度证明,这里就不详细写了,logn也是一个不准确的数)


代码也其实很好打,但就是证明需要扯进很多东西,这里就不详细讲了,问问度娘吧。。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值