定义

满足$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;
}

  

 

看都看了,顺手点个推荐呗 :)