博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[笔记] 线性筛小记
阅读量:4836 次
发布时间:2019-06-11

本文共 2993 字,大约阅读时间需要 9 分钟。

本文讲了

  1. 线性筛质数
  2. 线性筛$\varphi(n)$
  3. 线性筛$\mu(n)$
  4. 线性筛$d(n)$(因数个数)
  5. 线性筛$\sigma(n)$(约数和)

 

一、线性筛质数

  • 就扔个代码吧,具体详见
    inline void PRI(int n) {    for(R i=2;i<=n;++i) {        if(!v[i]) pri[++cnt]=i;        for(R j=1;j<=cnt&&i*pri[j]<=n;++j) {            v[i*pri[j]]=true; if(i%pri[j]==0) break;        }    }}

二、线性筛$\varphi(n)$

  • 也详见
    inline void PHI(int n) { p[1]=1;    for(R i=2;i<=n;++i) {        if(!v[i]) pri[++cnt]=i,p[i]=i-1;        for(R j=1;j<=cnt&&i*pri[j]<=n;++j) {            v[i*pri[j]]=true;             if(i%pri[j]==0) {p[i*pri[j]]=p[i]*pri[j]; break;}            p[i*pri[j]]=p[i]*p[pri[j]];        }    }}

三、线性筛$\mu(n)$

  • $\mu(n)=\begin{cases} 0&有平方素因子  \\ 1&素因子个数为偶数\\ -1&素因子个数为奇数\end{cases}$
  • 直接根据定义去筛
    inline void MU(int n) { mu[1]=1;    for(R i=2;i<=n;++i) {        if(!v[i]) pri[++cnt]=i,mu[i]=-1;        for(R j=1;j<=cnt&&i*pri[j]<=n;++j) {            v[i*pri[j]]=true;            if(i%pri[j]==0) break;            mu[i*pri[j]]=-mu[i];        }    } }

     

四、线性筛$d(n)$(因数个数)

  • 首先公式:$n=\prod_{i=1}^k\space p_i^{c_i}$,那么$d(n)=\prod_{i=1}^k\space (c_i+1)$
  • 记$d[n]$为$n$的因数个数,$c[n]$为$n$最小素因子出现次数;
    inline void D(int n) { d[1]=1;    for(R i=2;i<=n;++i) {        if(!v[i]) pri[++cnt]=i,d[i]=2,c[i]=1;        for(R j=1;j<=cnt&&i*pri[j]<=n;++j) {            v[i*pri[j]]=true;            if(i%pri[j]==0) {                c[i*pri[j]]=c[i]+1;                d[i*pri[j]]=d[i]/(c[i]+1)*(c[i]+2);                break;            } d[i*pri[j]]=d[i]*2;            c[i*pri[j]]=1;        }    }}
  • 若$i$是素数,则显然$d[i]=2,c[i]=1$
  • 若$i$不是素数,则要分类讨论
  1. 若$i%pri[j]==0$,说明$pri[j]$是$i$的最小素因子(因为素数是从小到大枚举的),所以$c[i*pri[j]]=c[i]+1$,而$d[i]=(c[i]+1)*(k_1+1)*(k_2+1)*...$,所以此时$c[i*pri[j]]$比$c[i]$增大了$1$,所以$d[i*pri[j]]=d[i]/(c[i]+1)*(c[i]+2)$
  2. 若$i%pri[j]!=0$,说明$pri[j]$是$i*pri[j]$的最小素因子,所以$c[i*pri[j]]=1$,对于$i$来说,相当于添了一个以前没有的素因子$pri[j]$,所以$d[i*pri[j]]=d[i]*2$.

五、线性筛$\sigma(n)$(约数和)

  • 首先公式:$n=\prod_{i=1}^k\space p_i^{c_i}$,那么$\sigma(n)=\prod_{i=1}^k 1+p_i+p_i^2+...+p_i^{c_i}=\prod_{i=1}^k\sum_{j=0}^{c_i} p_i^j$
  • 记$s[n]$为$n$的因数和,$c[n]$为$1+p_{min}+p_{min}^2+...+p_{min}^c$,其中$p_{min}$表示的是$n$的最小素因子,$c$是最小素因子在$n$中的的出现次数。
    inline void SIGMA() { s[1]=1;    for(R i=2;i<=n;++i) {        if(!v[i]) pri[++cnt]=i,s[i]=i+1,c[i]=i+1;        for(R j=1;j<=cnt&&i*pri[j]<=n;++j) {            v[i*pri[j]]=true;            if(i%pri[j]==0) {                c[i*pri[j]]=c[i]*pri[j]+1;                s[i*pri[j]]=s[i]/c[i]*c[i*pri[j]];                break;            } c[i*pri[j]]=pri[j]+1;            s[i*pri[j]]=s[i]*(pri[j]+1);        }    }}
  • 若$i$是素数,则显然$s[i]=i+1,c[i]=i+1$
  • 若$i$不是素数,则又要分类讨论
  1. 若$i%pri[j]==0$,说明$pri[j]$是$i$的最小素因子(因为素数是从小到大枚举的),所以原来的$\\1+p_{min}+p_{min}^2+...+p_{min}^c\\$,要变成$\\1+p_{min}+p_{min}^2+...+p_{min}^{c+1}\\$,所以在原来的基础上乘上$p$,再加个$1$就好了,所以$c[i*pri[j]]=c[i]*pri[j]+1$,而$d[i]=(c[i]+1)*(c_1+1)*(c_2+1)*...$,所以此时,$s[i*pri[j]]$也相应转化就好了。
  2. 若$i%pri[j]!=0$,说明$pri[j]$是$i*pri[j]$的最小素因子,所以$c[i*pri[j]]=pri[j]+1$,对于$i$来说,相当于添了一个以前没有的素因子$pri[j]$,所以$s[i*pri[j]]=s[i]*(pri[j]+1)$.

如果觉得我的四和五讲得不太清楚,安利一发


 

2019.06.08

转载于:https://www.cnblogs.com/Jackpei/p/10991603.html

你可能感兴趣的文章
7 Sentences You Shouldn't Say to Your Boss - EVER
查看>>
TurtleBot3-基础例程
查看>>
动态规划之矩阵链
查看>>
Chrome 中的 JavaScript 断点设置和调试技巧 (转载)
查看>>
在Linux shell脚本中root切换到普通用户执行脚本或命令的方法
查看>>
rem,em,px
查看>>
《TCP/IP 详解 卷1:协议》第 10 章:用户数据报协议
查看>>
前端学数据库之基础操作
查看>>
python模块pymysql
查看>>
Kafka与.net core(三)kafka操作
查看>>
jplayer.js 与 video.js
查看>>
Ubuntu mysql
查看>>
confluence-工具安装
查看>>
scrapy实战6爬取IT桔子国内所有融资公司:
查看>>
最小二乘法拟合直线
查看>>
1897. tank 坦克游戏
查看>>
57.二叉树的下一个节点——剑指offer
查看>>
angular.js ngbind nghtml ngTemplate
查看>>
nginx + rtmp 搭建流媒体服务器
查看>>
DAY-9 Linux基础及常用命令(5)
查看>>