满足$f(n)=f(a)*f(b)的性质 $(a与b互质)的函数被称为积性函数
求法因为该函数有这种性质,我们不用对于每一项都单独求解,利用这个性质可以在$O(n)$的时间内求出1~n的所有函数值
这样对于每个n,拆分成$n=\prod p_i^{a_i}$,这样$f(n)=\prod f(p_i^{a_i})$
具体而言,先用欧拉筛求出每个数n的最小质因数minp[n]
求完之后对于每一个数n,计算minp[n]对f(n)的贡献,然后将n除以minp[n],继续计算,如此反复直到n=1
应用判断一个函数是否是积性函数:看它是否能表示成其质因数函数值的乘积
常见积性函数:
φ(n) -欧拉函数
μ(n) -莫比乌斯函数:关于非平方数的质因子数目
gcd(n,k) -最大公因子,当k固定的情况
d(n) -n的正因子数目
$σ^k (n)$ -n的所有正因子的k次方之和
另外,还有如下性质:
两个积性函数的积和狄利克雷卷积、积性函数的k次方,也是积性函数
例题
【BZOJ1968】约数研究
求1~n的d(n)之和
代码
#include<bits/stdc++.h> using namespace std; #define N 1000000 bool tag[N]; int p[N/10],minp[N],ind[N],f[N],cnt; int qpow(int a,int b) { int res=1; while(b) { if(b&1) res*=a; a*=a; b>>=1; } return res; } int main() { int n; cin>>n; for(int i=2;i<=n;i++) { if(!tag[i]) p[++cnt]=i,minp[i]=i,ind[i]=1; for(int j=1;j<=cnt&&p[j]*i<=n;j++) { int t=p[j]*i; minp[t]=p[j]; tag[t]=true; if(i%p[j]==0) { ind[t]=ind[i]+1; break; } else ind[t]=1; } } f[1]=1; for(int i=2;i<=n;i++) { int x=i; f[i]=1; while(x>1) { f[i]*=(ind[x]+1); x/=qpow(minp[x],ind[x]); } } int tot=0; for(int i=1;i<=n;i++) tot+=f[i]; cout<<tot; }