【OI】线性筛
如何查找一个范围内的所有素数?
可以是从1~n挨个判断n%i 是否 == 0,也可以从 1~sqr(n) 一个个判断。
相信你们也听说过埃氏筛法,是使用每一个数的倍数筛掉合数!但是!每一个合数要被筛多次!这就给了我们优化的可乘之机!
它叫做线性筛,顾名思义,时间复杂度是线性的。
我们都知道,线性的复杂度已经非常优秀了,接下来我们的目的就是如何让每一个合数只被筛一次。
下面记住这条线性筛的原理:
每个合数只被它的最小质因子筛一次
每个合数只被它的最小质因子筛一次
每个合数只被它的最小质因子筛一次
重要的事情说三遍!!!
#include<iostream>
#include<cstdio> const int MaxN = 20025; bool notp[MaxN]; int prime[MaxN];
int tot; int main(){ int x;
scanf("%d",&x); for(int i = 2; i <= x; i++){
if(notp[i] == 0){
prime[++tot] = i; } for(int j = 1; j <= tot; j++){
if(i * prime[j] > x)
break; notp[i*prime[j]] = 1; if(i % prime[j] == 0)
break; } } for(int i = 1; i <= tot; i++){
printf("%d ",prime[i]);
} return 0;
}
看起来非常简短,对不对?
下面解释一下这段代码:
输入x,求0~x区间中的所有素数。
接下来,是2~x的枚举,为什么从2开始相信各位也都明白。
notp数组的意思是"is not a prime",不是一个质数,值为0时代表它是一个质数。(在开始我们已经把它默认设置为全为素数,尽管事实不是那样)
如果发现一个数"is not not a prime"(=="is a prime)就把它放到我们的素数数组里,至于为什么这么做稍后解答。(而且,我们显然可以看出这个数组具有单调递增的性质)
接下来我们就循环我们的素数数组,对于每个元素筛去它的质数倍。
相信 if ( i * prime[j] > x) break; 大家都理解,下面就是标记它是一个素数。
接下来就是重点!
线性筛全部的Knowledge都凝聚在这一句话!if ( i % prime[j] == 0 ) break;
它意味着,只有最小的质因数才能筛去其它的数。
因为,如果 i % prime[j] == 0 的话,这就是说 i 拥有一个最小的质因数 prime[j] ,原因有两条:①我们之前没有触发过 i % prime[j] == 0,那么就是说,之前的 prime[1~j]都不是i的任何因数。
② i % prime[j] == 0 意味着, i * prime[j] 等同于 prime[j] * i/prime[j] * prime[j] ,其中所有数均为整数,最小质因子就是 prime[j]。这违反了我们在一开始的原理:
每个合数只被它的最小质因子筛一次
而我们通过找规律发现,i * prime[j] 的最小质因子永远是素数序列中的prime[j]。
(例如,素数序列是 2,3,正在枚举4,4*2=8,最小质因子是2;素数序列是2,3,正在枚举3,2*3=6,3*3=9,2和3都是其中的最小质因子)
那么,接下来我们要注意一个事情。为什么 if( i % prime[j] == 0 ) break; 要放在 notp[i * prime[j]] = 1; 后面呢?难道不能放在它前面吗?
刚刚我解释过的原因①,在触发 if( i % prime[j] == 0 ) break; 意味着prime[j]是i最先遇到的质因子,并且我们知道某一个数的某个因子一定小于等于它本身,所以显而易见,我们的素数序列包括到i(无论i是否是质数)的所有质数(如果i是质数,那么包括i)。我们之前也说过这个质数序列是单调递增的,那么prime[j]就是 i 的最小质因子!
而我们之所以在筛完 i * prime[j] 之后才运行这个条件判断,是因为 i % prime[j] 第一次 == 0 的时候,prime[j]是i的最小质因子!如果这里不break,那么下一次 i % prime[k] == 0的时候,显而易见,prime[k]不是i的最小质因子,这违反了我们在开头给出的原理。为了避免某些合数将来被筛第二次,所以我们这里直接break,把筛掉剩下 i * prime[x] 的事情交给之后的质数序列去做。这样,就可以保证每个质数只被筛一次。
最后输出质数序列,相信各位都明白。
【OI】线性筛的更多相关文章
- 2018 南京网络预赛Sum - 线性筛
题意 链接 定义 $f(x)$ 为满足以下条件的有序二元组 $(a, b)$ 的方案数(即 $(a, b)$ 与 $(b, a)$ 被认为是不同的方案): $x= ab$ $a$ 和 $b$ 均无平方 ...
- bzoj2693--莫比乌斯反演+积性函数线性筛
推导: 设d=gcd(i,j) 利用莫比乌斯函数的性质 令sum(x,y)=(x*(x+1)/2)*(y*(y+1)/2) 令T=d*t 设f(T)= T可以分块.又由于μ是积性函数,积性函数的约束和 ...
- BZOJ 2693: jzptab [莫比乌斯反演 线性筛]
2693: jzptab Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1194 Solved: 455[Submit][Status][Discu ...
- BZOJ 2818: Gcd [欧拉函数 质数 线性筛]【学习笔记】
2818: Gcd Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4436 Solved: 1957[Submit][Status][Discuss ...
- 【BZOJ-4514】数字配对 最大费用最大流 + 质因数分解 + 二分图 + 贪心 + 线性筛
4514: [Sdoi2016]数字配对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 726 Solved: 309[Submit][Status ...
- 洛谷P3383 【模板】线性筛素数
P3383 [模板]线性筛素数 256通过 579提交 题目提供者HansBug 标签 难度普及- 提交 讨论 题解 最新讨论 Too many or Too few lines 样例解释有问题 ...
- 【BZOJ-4407】于神之怒加强版 莫比乌斯反演 + 线性筛
4407: 于神之怒加强版 Time Limit: 80 Sec Memory Limit: 512 MBSubmit: 241 Solved: 119[Submit][Status][Discu ...
- BZOJ-2186 沙拉公主的困惑 线性筛(筛筛筛)+线性推逆元
2186: [Sdoi2008]沙拉公主的困惑 Time Limit: 10 Sec Memory Limit: 259 MB Submit: 2417 Solved: 803 [Submit][St ...
- Bzoj 2186: [Sdoi2008]沙拉公主的困惑 乘法逆元,线性筛,欧拉函数,数论
2186: [Sdoi2008]沙拉公主的困惑 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 2560 Solved: 857[Submit][St ...
随机推荐
- eclipse包分层
方法很简单,如下图所示: 1.点击项目栏窗口的右上角的倒三角 2.选择Pachage Presentation(包呈现) 3.选择Hierarchical(分层)
- 模板BSGS(SDOI2011计算器) 模板EXBSGS
BSGS和EXBSGS是OI中用于解决A^xΞB(mod C)的常用算法. 1.BSGS BSGS用于A,C互质的情况. 令m=sqrt(C),此时x可表示为i*m+j. 式中i和j都<=sqr ...
- 笔试算法题(08):输出倒数第K个节点
出题:输入一个单向链表,要求输出链表中倒数第K个节点 分析:利用等差指针,指针A先行K步,然后指针B从链表头与A同步前进,当A到达链表尾时B指向的节点就是倒数第K个节点: 解题: struct Nod ...
- [Python3网络爬虫开发实战] 1.9.4-Scrapyd API的安装
安装好了Scrapyd之后,我们可以直接请求它提供的API来获取当前主机的Scrapy任务运行状况.比如,某台主机的IP为192.168.1.1,则可以直接运行如下命令获取当前主机的所有Scrapy项 ...
- PHP实现微信第三方登录的方法
本文实例讲述了PHP版微信第三方实现一键登录及获取用户信息的方法.分享给大家供大家参考,具体如下: 注意,要使用微信在第三方网页登录是需要“服务号”才可以哦,所以必须到官方申请 一开始你需要进入微信公 ...
- 如何转成libsvm支持的数据格式并做回归分析
本次实验的数据是来自老师给的2006-2008年的日期,24小时的温度.电力负荷数据,以及2009年的日期,24小时的温度数据,目的是预测2009年每天24小时的电力负荷,实验数据本文不予给出. 用l ...
- 【转】ASP.NET MVC 4 RC的JS/CSS打包压缩功能
原文链接:http://www.cnblogs.com/shanyou/archive/2012/06/22/2558580.html 打包(Bundling)及压缩(Minification)指的是 ...
- hdu 1814 2-sat 输出字典最小的和任意序列的 模板题
/* 思路:http://blog.csdn.net/string_yi/article/details/12686873 hdu 1814 输出字典序最小的2-sat */ #include< ...
- msp430入门编程04
msp430中C语言的变量与数据类型 msp430入门学习 msp430入门编程
- Linux下汇编语言学习笔记34 ---
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...