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
  • 相关阅读:
    mac下git中文乱码
    sublime安装插件
    Vue + ElementUI的电商管理系统实例08 角色列表
    Vue + ElementUI的电商管理系统实例07 权限列表
    Vue + ElementUI的电商管理系统实例06 删除用户
    Vue + ElementUI的电商管理系统实例05 修改用户
    Vue + ElementUI的电商管理系统实例04 添加用户
    Vue + ElementUI的电商管理系统实例03 用户列表
    Vue + ElementUI的电商管理系统实例02 主页
    Vue 项目中的ESlint语法报错问题
  • 原文地址:https://www.cnblogs.com/yang-RA-NOI/p/13434831.html
Copyright © 2011-2022 走看看