zoukankan      html  css  js  c++  java
  • 素数筛

    对于一些题,我们需要去枚举n以下的素数,
    但是有时可能不止一个数需要这样做,所以下面介绍一些筛出n以下的素数的方法

    一.暴力求解

    直接枚举每一个(iin[2,n]),判断其是否是素数,然后加入数组
    判断素数的话枚举(jin[2,sqrt i]),判断是否i能整除j,若都不能,则i为素数
    代码比较简单,时间复杂度最高,为(O(nsqrt n))

    for(int i=2;i<=n;i++){
    	bool f=true;;
    	for(int j=2;j<=sqrt(i);j++)if(i%j==0)f=false;
    	if(f)cout<<i<<endl;
    }
    

    输出的即为n以内的所有素数

    二.优化一下

    当然,是素数的放在q数组中,
    那其实有一些数可以被它的因数筛掉,也就是加个标记
    之后看到直接跳过判断
    所以判断也不需要(sqrt n)的时间了
    若到它时它仍未被访问过,则它就是个素数
    这样的时间复杂度可以被减为比(O(n))大一点的了
    代码的话如下:

    for(int i=2;i<=n;i++){
    	if(!vis[i])q[++cnt]=i;
    	for(int j=1;i*j<=n;j++)vis[i*j]=1;
    }
    

    进一步优化

    我们会发现优化的代码中(j)是从(1→n/i)
    那么难免会碰到一些无用的步骤
    如枚举(k)(j)时会循环出现(1→k-1),会有一定的重复标记
    为了避免,我们可以不枚举筛(i imes j),可以去筛(i imes p[j])
    (p[j]==i)的因子时就可以跳出循环
    因为(j)之后的某个(k)而产生的(p[k] imes i)可以被(p[j]整除)
    则之后这个(p[k] imes i)可以被(p[j])筛掉,则此时无需多筛
    时间复杂度接近(O(n)),代码也不怎么长

    for(int i=2;i<=n;i++){
    	if(!vis[i])q[++cnt]=i;
    	for(int j=1;p[j]*i<=n;j++){
    		vis[i*p[j]]=1;
    		if(i%p[j]==0)break;
    	}
    }
    

    总结

    其实最后优化出的就是经典的欧拉筛
    其实有些题预处理时暴力也可以……
    但是这样也没多多少,代码也快了不少
    所以提倡记熟欧拉筛
    偷偷说一句,打表好像更快
    如果有所遗漏,望大佬们在评论中加以补充
    好了就这样了,下期再见!

    Reality&Imagine
  • 相关阅读:
    归并排序处理复杂对象例子
    Java归并排序的递归与非递归实现
    Java实现一个双向链表的倒置功能
    Node<T> 的作用
    Tomcat控制台总是打印日志问题的解决办法
    git回滚部分文件到某个版本
    ios-deploy was not found
    Ionic3的http请求如何实现token验证,并且超时返回登录页
    Ionic开发遇到的坑整理
    使用gradle命令代替CUBA Studio,启动项目
  • 原文地址:https://www.cnblogs.com/yang-RA-NOI/p/13434831.html
Copyright © 2011-2022 走看看