筛法板子
发现自己一般推完莫反后不会筛,所以回来看看。
常用线性筛来筛质数同时得到各个积性函数的值。
先说几个常用的东西怎么筛,首先约数个数和的筛法.
\(O(nlog\ n)\)的筛法是显然的,不多说(调和级数枚举倍数)。
注:下面p为质数,s为n中分解出的质因子的指数。
就还是先看我们要求的目标,直接唯一分解定理,我们的目标是\(d_x\)为约数个数。
\[d_x=\prod_{p_i|x}s_i+1
\]
然后这个东西还是分情况讨论去筛。
对于质因数来说,\(d_x=2\)
考虑我们现在找到一个不能整除x的质因数:
\[d_{x×p_i}=d_x×2
\]
这个显然。
如果找到一个可以整除x的质因数,\(s_i\)是x的质因子\(p_i\)的指数:
\[d_{x×p_i}=d_x/(s_i+1)×(s_i+2)
\]
这个可以维护下\(s_i\),那么:
\[s_{ i_{(x×p_i)}}=s_{i_x}+1
\]
对于质数该值为1,然后直接筛即可。
f[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]) p[++tot]=i,f[i]=2,g[i]=1;
for(int j=1;j<=tot&&i*p[j]<=n;j++){
int tmp=i*p[j];
vis[tmp]=1;
if(i%p[j]==0){
mu[tmp]=0;
g[tmp]=g[i]+1;
f[tmp]=f[i]/(g[i]+1)*(g[tmp]+1);
break;
}
g[tmp]=1;
f[tmp]=f[i]*[g[tmp]+1];
mu[tmp]=-mu[i];
}
}
然后是约数和。
\(O(nlog\ n)\)不说了。
考虑将一个数根据唯一分解定理分解。
\[n=\prod_{p_i|n}p_i^{s_i}
\]
那么有n的约数和\(\sigma(n)\)满足
\[\sigma(n)=\prod_{p_i|n}\sum_{j=0}^{s_i}p_i^j
\]
筛的时候只有两种情况,一种该因数在当前基数i中没有出现过。
那么有:
\[\sigma(i×p_k)=\sigma(i)×(p_k+1)
\]
另外一种情况则是该因数出现过(\(s_k\)表示在i中\(p_k\)的指数):
\[\sigma(i×p_k)=\sigma(i)×\sum_{j=0}^{s_k+1}p_k^j/\sum_{j=0}^{s_k}p_k^j
\]
然后可以发现后面的两个东西可以单独维护,而且二者之间存在关系(设该值在i上为\(g_i\)):
\[g_{i×p_k}=g_i×p_k+1
\]
然后就可以线性筛了。
mu[1]=1,g[1]=1,f[1]=1;
for(int i=2;i<=s;++i){
if(!vis[i])p[++tot]=i,mu[i]=-1;
for(int j=1;j<=tot&&p[j]*i<=s;++j){
int tmp=i*p[j];
vis[tmp]=1;
if(!(i%p[j])){
mu[tmp]=0;
g[tmp]=g[i]*p[j]+1;
f[tmp]=f[i]/g[i]*g[tmp];
break;
}
g[tmp]=p[j]+1;
f[tmp]=f[tmp]*f[p[j]];
mu[tmp]=-mu[i];
}
}
因为有
\[\sum_{i=0}^{k}x^k=(x^{k+1}-1)/(x-1)
\]
这个东西还可以写成另一个形式:
mu[1]=f[1]=g[1]=1;
for(int i=2;i<=s;++i){
if(!vis[i])p[++tot]=i,mu[i]=-1,pw[i]=i*i,f[i]=i+1;
for(int j=1;j<=tot&&p[j]*i<=s;++j){
int tmp=i*p[j];
vis[tmp]=1;
if(!(i%p[j])){
mu[tmp]=0;
pw[tmp]=pw[i]*p[j];
f[tmp]=f[i]*(pw[tmp]-1)/(pw[i]-1);
break;
}
pw[tmp]=p[j]*p[j];
f[tmp]=f[tmp]*f[p[j]];
mu[tmp]=-mu[i];
}
}
https://www.cnblogs.com/shining-like-stars