今天来玩玩筛

英文:Sieve

有什么筛?

这里介绍:素数筛,欧拉筛,约数个数筛,约数和筛

为什么要用筛?

顾名思义,筛就是要漏掉没用的,留下有用的。最终筛出来1~n的数的一些信息。

为什么要用线性筛?

考虑最基础的线性筛素数,是O(n)的。

而一般的做法是:

1.对于每个m暴力枚举1~sqrt(m)看能否被整除。O(nsqrt(n))

2.对于每个找到的素数,用它去将所有它的倍数的数都干掉。O(nlogn)

但是,即使是第二种,也有一个log

这是因为一个合数会被它的所有质因子筛一次。要重复质因子个数次,除第一次之外都没用。

所以用线性筛

线性筛原理:

一个算法,使得每个合数只被它的最小质因子筛一次。

怎么保证呢?

素数线性筛:

先看代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=+;
  4. int ps[N],cnt;
  5. bool v[N];
  6. int n,m;
  7. void sieve(){
  8. for(int i=;i<=n;i++){
  9. if(v[i]==){
  10. ps[++cnt]=i;
  11. }
  12. for(int j=;j<=cnt;j++){
  13. if(i*ps[j]>n) break;
  14. v[i*ps[j]]=;
  15. if(i%ps[j]==) break;
  16. }
  17. }
  18. }
  19. int main()
  20. {
  21. scanf("%d%d",&n,&m);
  22. sieve();
  23. v[]=;
  24. int t;
  25. for(int i=;i<=m;i++){
  26. scanf("%d",&t);
  27. if(v[t]) printf("No\n");
  28. else puts("Yes");
  29. }
  30. return ;
  31. }

看不懂...................

解释:
对于一个质数,之前没有被标记。肯定只会有一次查到。把它记录到素数集合里去。

然后,不论这个数是否为质数,都将已有的质数从1~cnt循环一遍,把所有的i*ps[j]标记。

当i*ps>n break,可以理解。

当i%ps==0 break.???

这个时候,ps和i不互质了,而ps第一次整除i,所以ps就是i的最小质因数。叫他ps0

而之后,ps更大,ps*i的最小质因数就不是ps了。因为i里有ps0,这个合数就等着以后i更大了,通过ps0筛掉。

ps再大,后面的ps*i的最小质因数都不是ps,所以之前直接break掉就好。

由于每个合数只会被i*ps的形式找到一次(那一次的ps就是这个合数的最小质因子)。而内层循环每一次都对应一个将v[ps*i]=1的操作。

所以内层循环均摊O(1),总共O(n)

完毕。

欧拉线性筛:

代码:fai(i) 1~i中和i互质的数的个数。

可以容斥推出公式:假设:i=p1^q1*p2^q2*....pn^qn

那么,fai(i)=p1^(q1-1)*(p1-1) * p2^(q2-1)*(p2-1) * ......pn^(qn-1) * (pn-1)

证明不是本篇想讲的。

  1. void sieve(){
       fai[]=;
  2. for(int i=;i<=n;i++){
  3. if(v[i]==){
  4. fai[i]=i-;
  5. pri[++cnt]=i;
  6. }
  7. for(int j=;j<=cnt;j++){
  8. if(i*pri[j]>n) break;
  9. v[i*pri[j]]=;
  10. if(i%pri[j]==) {
  11. fai[i*pri[j]]=fai[i]*pri[j];break;
  12. }
  13. else{
  14. fai[i*pri[j]]=fai[i]*(pri[j]-);
  15. }
  16. }
  17. }
  18. }

并不想从积性函数性质入手解释。

显然的,当处理到fai[i]的时候,i的值应该就知道了。i是质数就现成赋值。

考虑公式。

当i%ps==0 时,i的质因子中有ps,那么i*ps的质因子ps的次数就大于一,那么,就是fai[i]*ps了

否则,i*ps 的 ps的次数就是1,那么,ps^(1-1)*(ps-1)=(ps-1) 所以是fai[i]*(ps-1)

之后的各种操作基于线性筛的要求和特质。(即每个数只被它的最小质因子筛一次)

例题:SDOI2008 仪仗队

约数个数线性筛:

推荐:线性筛约数个数和、约数和

设x=p1^q1*p2^q2*....pn^qn

要知道公式:个数=(q1+1)*(q2+1)*...*(qn+1) 乘法原理就可以知道。

设t[i]表示i的约数个数

设e[i]表示i的最小素因子个数

①i是质数:t[i]=2,e[i]=1;

②i%pj!=0 这个时候,pj里面没有i,根据积性函数,或者乘法原理,t[i*pj]=t[i]*t[pj]=2t[i];

而 e[i*pj]=1

③i%pj==0 这个时候,pj里面至少有一个i,i也是pj的最小质因子。

t[i*pj]=t[i]/(e[i]+1)*(e[i]+2) 考虑公式,i*pj只在pj的位置上加了1,所以先除掉,再乘上去。

e[i*pj]=e[i]+1 最小素因子个数多了一个。

约数和的线性筛:

推荐:线性筛 [约数个数/约数和]

(很详细的解释)

设x=p1^q1*p2^q2*....pn^qn

首先还是要知道公式:和=(1+p1^1+...+p1^q1)*(1+p2^1+...+p2^q2)*...*(1+pn^1+...+pn^qn)

证明很简单,加数的个数显然就是约数个数,每次选择就是这个约数个数的质因数分解形式,数值就是这个约数的数值。

设t[i]表示i的约数和

设e[i]表示i的最小素因子对约数和的答案的贡献,即:(1+p1^1+...+p1^q1)(假设p1是最小质因子)

①当i是质数的时候,t[i]=i+1;e[i]=i+1;

②i%pj!=0 根据公式、积性函数性质 : t[i*pj]=t[i]*t[pj]

e[i*pj]=1+pj;

③i%pj==0

t[i*pj]=t[i]/e[i]*(pj*e[i]+1)

证明:考虑公式,i里面有pj的贡献,乘了一个pj,相当于多了一个pj^(qj+1)所以除掉后,乘上错位,再加一

而 e[i*pj]=e[i]*pj+1

就这样。代码参考上面的写就是了,没什么难度。

莫比乌斯函数筛:

知道定义就好说:

μ(i)={

0 i有平方因子

1 i的质因子个数为偶数

-1 i的质因子个数为奇数

}

根据定义直接筛就好了。

  1. void sieve(){
  2. u[]=;
  3. for(int i=;i<=N;i++){
  4. if(!vis[i]){
  5. u[i]=-;
  6. pr[++cnt]=i;
  7. }
  8. for(int j=;j<=cnt;j++){
  9. if(pr[j]*i>N) break;
  10. vis[pr[j]*i]=;
  11. if(i%pr[j]==) {
  12. u[pr[j]*i]=;break;
  13. }
  14. else u[pr[j]*i]=-u[i];
  15. }
  16. }
  17. }

例题:bzoj2440 完全平方数

SIEVE 线性筛的更多相关文章

  1. BZOJ 2693: jzptab [莫比乌斯反演 线性筛]

    2693: jzptab Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1194  Solved: 455[Submit][Status][Discu ...

  2. BZOJ 2818: Gcd [欧拉函数 质数 线性筛]【学习笔记】

    2818: Gcd Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4436  Solved: 1957[Submit][Status][Discuss ...

  3. BZOJ 3309: DZY Loves Math [莫比乌斯反演 线性筛]

    题意:\(f(n)\)为n的质因子分解中的最大幂指数,求\(\sum_{i=1}^n \sum_{j=1}^m f(gcd(i,j))\) 套路推♂倒 \[ \sum_{D=1}^n \sum_{d| ...

  4. Codeforces 893E Counting Arrays:dp + 线性筛 + 分解质因数 + 组合数结论

    题目链接:http://codeforces.com/problemset/problem/893/E 题意: 共q组数据(q <= 10^5),每组数据给定x,y(x,y <= 10^6 ...

  5. 洛谷 - P1891 - 疯狂LCM - 线性筛

    另一道数据范围不一样的题:https://www.cnblogs.com/Yinku/p/10987912.html $F(n)=\sum\limits_{i=1}^{n} lcm(i,n) $ $\ ...

  6. Codeforces 1047C (线性筛+因数分解)

    题面 传送门 分析 1.暴力做法 首先先把每个数除以gcd(a1,a2-,an)gcd(a_1,a_2 \dots,a_n )gcd(a1​,a2​-,an​) 可以O(namax)O(n\sqrt ...

  7. 莫比乌斯反演/线性筛/积性函数/杜教筛/min25筛 学习笔记

    最近重新系统地学了下这几个知识点,以前没发现他们的联系,这次总结一下. 莫比乌斯反演入门:https://blog.csdn.net/litble/article/details/72804050 线 ...

  8. bzoj2693--莫比乌斯反演+积性函数线性筛

    推导: 设d=gcd(i,j) 利用莫比乌斯函数的性质 令sum(x,y)=(x*(x+1)/2)*(y*(y+1)/2) 令T=d*t 设f(T)= T可以分块.又由于μ是积性函数,积性函数的约束和 ...

  9. 【BZOJ-4514】数字配对 最大费用最大流 + 质因数分解 + 二分图 + 贪心 + 线性筛

    4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 726  Solved: 309[Submit][Status ...

随机推荐

  1. springboot+websocket 归纳收集

    websocket是h5后的技术,主要实现是一个长连接跟tomcat的comet技术差不多,但websocket是基于web协议的,有更广泛的支持.当然,在处理高并发的情况下,可以结合tomcat的a ...

  2. hexo——轻量、简易、高逼格的博客

    背景 写blog虽然经历了N多不同时代的产品,恒久不变的始终是自己无人问津的网站.虽然没几个人看,还是隔断时间就要折腾一下.从最开始的wordpress,到tale,到现在的hexo,网站变得越来越简 ...

  3. CentOS7中安装redis5.0

    1. 环境介绍 CentOS7 (未安装Development Tools) 2. 下载Redis5.0-rc3 wget -O redis-5.0-rc3.tar.gz https://github ...

  4. mysql连接数设置操作(Too many connections)及设置md5值的加密密码

    mysql在使用过程中,发现连接数超了~~~~ [root@linux-node1 ~]# mysql -u glance -h 192.168.1.17 -pEnter password: ERRO ...

  5. 使用rem进行自适应页面布局

    设计师给到我们前端的设计稿一般是按照iphone6屏幕(iphone6 两倍屏 设备 分辨率(物理尺寸) 屏幕宽高 PPI 状态栏高度 导航栏高度 标签栏高度 iPhone6 750×1334 px ...

  6. 函数:this & return、break、continue、exit()

    this this:的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象在调用的时候才能决定,谁调用的就指向谁. 情景1:指向 ...

  7. 软件工程驻足篇章:第十七周和BugPhobia团队漫长的道别

    0x01 :序言 I am a slow walker, but I never walk backwards. 成长于被爱,学着爱人 成长的故事 也是年少的星期六结束的故事 就仿佛我和BugPhob ...

  8. David Silver强化学习Lecture2:马尔可夫决策过程

    课件:Lecture 2: Markov Decision Processes 视频:David Silver深度强化学习第2课 - 简介 (中文字幕) 马尔可夫过程 马尔可夫决策过程简介 马尔可夫决 ...

  9. 服务器端发送邮件签名采用Data URI scheme包含图片

    要在服务器端基于HTML,拼接邮件内容,原来用户使用outlook采用了邮件签名,签名里含有公司Logo的图片,Outlook的msg文件里是专有的cid:xxxx,这里借用Data URI sche ...

  10. [转帖]浅析Servlet执行原理

    浅析Servlet执行原理 原贴地址: https://www.cnblogs.com/wangjiming/p/10360327.html 原作者画的图挺好. 自己之前看过iis的一些配置文档 但是 ...