关于线性筛及其扩展
关于线性筛及其扩展
xjb讲
顾名思义,是一种复杂度为线性的筛法
常用来求素数
不过她的扩展用法也是蛮多的
比如她可以用来求大多数积性函数 (当然,你要会,才能求)
积性函数
积性函数指对于所有互质的整数a和b有性质f(ab)=f(a)f(b)的数论函数
即,对于一个数论函数
常见的积性函数:欧拉函数
原理
首先积性函数
在原有线性筛中额外求一个数组
即:
在线性筛结束之后,从
当
例:
至此,我们便实现了线性筛的扩展
线性筛(欧拉筛)求素数
思路
也是很简单的:保证每个数只被它最小的因数筛去一次
code
Elaina's code
int prime[N]; // 保存素数
bool is_prime[N];
// 筛选 n 以内的所有素数
void xxs(int n){
memset(is_prime,1,sizeof(is_prime));
is_prime[0]=is_prime[1]=0; // 0和1都不是素数
for(int i=2;i<=n;++i){
if(is_prime[i]){// 如果i是素数
prime[++prime[0]]=i;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=n;++j){
is_prime[i*prime[j]]=0;
// 如果i中包含了该质因子,则停止
if(i%prime[j]==0) break;
}
}
}
欧拉函数
思路
首先,我们知道欧拉函数表示为
其中
注意到在线性筛中,每一个合数都是被最小的质因子筛掉
比如设
观察线性筛的过程,我们还需要处理两个部分,下面对
-
如果
,那么 包含了 的所有质因子 -
如果
,这时 和 是互质的,根据欧拉函数性质,我们有:
code
Elaina's code
int n,phi[N],prime[N],cnt;
bool pri[N];
void Euler(){
mst(pri,1);
phi[1]=1;
for(int i=2;i<=n;i++){
if(pri[i]){
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt;j++){
int k=i*prime[j];
if(k>n){
break;
}
pri[k]=0;
if(i%prime[j]==0){
phi[k]=prime[j]*phi[i];
break;
}else{
phi[k]=(prime[j]-1)*phi[i];
}
}
}
}
莫比乌斯函数
学了再说吧 Ciallo~(∠・ω< )⌒☆
筛法求约数个数
前置
用
约数个数定理
由唯一分解定理,
对于一个大于
则
证明
用到乘法原理
我不会! 自豪.jpg
思路
-
当
为质数时,(很显然对吧),同时设 ,其中 为 的最小质因子 -
当
为 的质因子时,
- 当
互质时,
code
Elaina's code
int prime[N];
int d[N],num[N];
bool pri[N];
void pre(int n){
d[1]=1;
mst(pri,1);
pri[0]=pri[1]=0;
for(int i=2;i<=n;++i){
if(pri[i]){
prime[++prime[0]]=i;
d[i]=2;
num[i]=1;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=n;++j){
pri[i*prime[j]]=0;
if(i%prime[j]==0){
num[i*prime[j]]=num[i]+1;
d[i*prime[j]]=d[i]/num[i*prime[j]]*(num[i*prime[j]]+1);
break;
}
num[i*prime[j]]=1;
d[i*prime[j]]=d[i]*2;
}
}
}
筛法求约数和
这个就比较简单了
直接看码
设
Elaina's code
int prime[N];
int g[N],f[N];
bool pri[N];
void pre(int n){
g[1]=f[1]=1;
mst(pri,1);
pri[0]=pri[1]=0;
for(int i=2;i<=n;++i){
if(pri[i]){
prime[++prime[0]]=i;
g[i]=i+1;
f[i]=i+1;
}
for(int j=1;j<=prime[0]&&i*prime[j]<=n;++j){
pri[i*prime[j]]=0;
if(i%prime[j]==0){
g[i*prime[j]]=g[i]*prime[j]+1;
f[i*prime[j]]=f[i]/g[i]*g[i*prime[j]];
break;
}
f[i*prime[j]]=f[i]*f[prime[j]];
g[i*prime[j]]=1+prime[j];
}
}
}
结语
奖励自己一张图吧~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本