埃氏筛
枚举质数 \(p_i\) ,每次去除所有是 \(p_i\) 倍数的数,总效率大概是 \(O(n\log\log n)\) 。
int _prm=0,prm[M];bool isprm[M];
void Get_phi(int n){
for(int i=2;i<=n;i++){
if(isprm[i]) continue ;
prm[++_prm]=i;
for(int j=i*i;j<=n;j+=i) isprm[j]=1;
}
}
值得一提的,可以通过模拟埃氏筛来快速求得区间素数,处理方式和 Min_25 筛的一部分很像。
线性筛
自行理解吧(
int _prm=0,prm[M];bool isprm[M];
void Pri(int n){
for(int i=2;i<=n;i++){
if(!isprm[i]) prm[++_prm]=i;
for(int j=1;j<=_prm&&i*prm[j]<=n;j++){
isprm[i*prm[j]]=1;
if(i%prm[j]==0) break;
}
}
}
杜教筛
给出一个积性函数 \(f(x)\) ,求出 \(S(n)=\sum\limits_{i=1}^n f(i)\) 。
\(n\le 10^9\)
利用狄利克雷卷积,找出一个积性函数 \(g(x)\) 。
\[\begin{aligned} \end{aligned} \]\[\begin{aligned} \sum\limits_{i=1}^n (f*g)(i)=\sum\limits_{i=1}^n \sum\limits_{d|i} f(d)\times g(\frac{i}{d}) \end{aligned} \]\[\begin{aligned} =\sum\limits_{d=1}^n g(d) \sum\limits_{i=1}^{⌊\frac{n}{d}⌋} f(i) \end{aligned} \]\[\begin{aligned} =\sum\limits_{d=1}^n g(d)\times S(⌊\frac{n}{d}⌋) \end{aligned} \]如果知道了 \(g(1)S(n)\) , \(S(n)\) 自然也可以求出来。
\[\begin{aligned} g(1)S(n)=\sum\limits_{d=1}^n g(d)\times S(⌊\frac{n}{d}⌋)-\sum\limits_{d=2}^n g(d)\times S(⌊\frac{n}{d}⌋) \end{aligned} \]\[\begin{aligned} =\sum\limits_{i=1}^n (f*g)(i)-\sum\limits_{d=2}^n g(d)\times S(⌊\frac{n}{d}⌋) \end{aligned} \]如果找的那个 \(g(x)\) 可以在很短的时间内算出\(g(x)\) 和 \((f*g)(x)\) 的前缀和 ,那么就可以通过数论分块来递归求解。
假设求 \(g(x)\) 和 \((f*g)(x)\) 的前缀和的复杂度为常数,总的复杂度为 \(\mathcal{O(n^{\frac{3}{4}})}\) 。
经典杜教筛套路
\[f(n)=μ(n)\ \ \ \ \ g(n)=1\ \ \ \ \ (f*g)(n)=[n==1] \]int _prm=0,prm[M],mu[M],pre_mu[M];bool isprm[M];
void Get_Mu(int n){
mu[1]=pre_mu[1]=1;
for(int i=2;i<=n;i++){
if(!isprm[i]) prm[++_prm]=i,mu[i]=-1;
for(int j=1;j<=_prm&&i*prm[j]<=n;j++){
isprm[i*prm[j]]=1;
if(i%prm[j]==0) break;
mu[i*prm[j]]=-mu[i];
}
pre_mu[i]=pre_mu[i-1]+mu[i];
}
}
map<int,int> Smu;
int Sum_mu(int n){
if(n<M) return pre_mu[n];
if(Smu[n]) return Smu[n];
int res=1;
for(int l=2,r=0;l<=n;l=r+1){
r=(n/(n/l));
res-=(r-l+1)*Sum_mu(n/l);
}
return Smu[n]=res;
}
\[f(n)=φ(n)\ \ \ \ \ g(n)=1\ \ \ \ \ (f*g)(n)=n
\]int _prm=0,prm[M],phi[M],pre_phi[M];bool isprm[M];
void Get_Phi(int n){
phi[1]=pre_phi[1]=1;
for(int i=2;i<=n;i++){
if(!isprm[i]) prm[++_prm]=i,phi[i]=i-1;
for(int j=1;j<=_prm&&i*prm[j]<=n;j++){
isprm[i*prm[j]]=1;
if(i%prm[j]==0){
phi[i*prm[j]]=phi[i]*prm[j];
break;
}
phi[i*prm[j]]=phi[i]*(prm[j]-1);
}
pre_phi[i]=pre_phi[i-1]+phi[i];
}
}
map<int,int> Sphi;
int Sum_phi(int n){
if(n<M) return pre_phi[n];
if(Sphi[n]) return Sphi[n];
int res=n*(n+1)/2;
for(int l=2,r=0;l<=n;l=r+1){
r=(n/(n/l));
res-=(r-l+1)*Sum_phi(n/l);
}
return Sphi[n]=res;
}
\[f(n)=n×φ(n)\ \ \ \ \ g(n)=n\ \ \ \ \ (f*g)(n)=n^2
\]Min_25筛
这是一个大力推一波不知有何用的式子,然后我也不知道怎么证明但是复杂度就是 \(\mathcal{O(\frac{n^{\frac{3}{4}}}{\log n})}\) 的神仙筛法。
标签:frac,limits,筛法,int,sum,笔记,学习,prm,aligned From: https://www.cnblogs.com/wzp-blog/p/13736210.html