莫比乌斯反演

引理
\(\forall a,b,c \in Z,\left\lfloor \frac{a}{bc} \right\rfloor=\left\lfloor \frac{\left\lfloor \frac{a}{b} \right\rfloor}{c} \right\rfloor\)
证明:
\(\frac{a}{b}=\left\lfloor \frac{a}{b} \right\rfloor+r\) (\(0 \leq r < 1\))
\(\left\lfloor \frac{a}{bc} \right\rfloor=\left\lfloor \frac{\left\lfloor \frac{a}{b} \right\rfloor}{c} + \frac{r}{c}\right\rfloor=\left\lfloor \frac{\left\lfloor \frac{a}{b} \right\rfloor}{c} \right\rfloor\)

数论分块

基本形式:
\(\sum \limits_{i=1}^n \left\lfloor \frac{n}{i} \right\rfloor\)
对于每一个 \(i\) ,可以发现: \(\lfloor \frac{n}{i} \rfloor\) 的每一种值呈块状分布。
所以,对于任意一个 \(i\) (\(i \leq n\)) ,需要找到一个最大的 \(j\) (\(i \leq j \leq n\)) ,使得 \(\left\lfloor \frac{n}{i} \right\rfloor=\left\lfloor \frac{n}{j} \right\rfloor\)
此时,\(j=\left\lfloor \frac{n}{\left\lfloor \frac{n}{i} \right\rfloor} \right\rfloor\)
考虑证明这一结论。
首先,证明 \(i \leq j \leq n\)
显然, \(j \leq n\) ,所以,只需证明 \(i \leq j\)
\(\left\lfloor \frac{n}{\left\lfloor \frac{n}{i} \right\rfloor} \right\rfloor \geq \left\lfloor \frac{n}{\frac{n}{i}} \right\rfloor=\left\lfloor i \right\rfloor=i\)
所以 \(i \leq j\)
接下来,设 \(k=\left\lfloor \frac{n}{i} \right\rfloor\) ,考虑证明 \(j=\left\lfloor \frac{n}{k} \right\rfloor\) 为满足 \(\left\lfloor \frac{n}{j} \right\rfloor=k\) 的最大值。
\(\left\lfloor \frac{n}{j} \right\rfloor =k \Rightarrow k \leq \frac{n}{j} <k+1 \Rightarrow \frac{1}{k+1} < \frac{j}{n} \leq \frac{1}{k} \Rightarrow \frac{n}{k+1} <j \leq \frac{n}{k}\)
又因为 \(j\) 是整数,所以 \(j_{max}=\left\lfloor \frac{n}{k} \right\rfloor\)
所以,每次以 \([i,j]\) 为一块,直接算即可。
例题
\(\sum \limits_{i=1}^n k \bmod i=\sum \limits_{i=1}^n k-i \times \left\lfloor \frac{k}{i} \right\rfloor\)
直接数论分块算即可。

ans=n*k;
while(l<=n)
{
	l=r+1;
	if(k/l) r=MIN(k/(k/l),n);
	else r=n;
	ans-=(k/l)*(l+r)*(r-l+1)/2;
}

二维数论分块
考虑一个二维的版本。
\(\sum \limits_{i=1}^{min(n,m)} \left\lfloor \frac{n}{i} \right\rfloor \left\lfloor \frac{m}{i} \right\rfloor\)
把代码中 r=n/(n/l) 替换为 r=min(n/(n/l),m/(m/l)) 即可。

狄利克雷卷积

定义
定义两个数论函数 \(f,g\) 的狄利克雷卷积为:
\((f*g)(n)=\sum \limits_{d|n}f(d)g(\frac{n}{d})\)
性质
1.交换律:\(f*g=g*f\)
2.结合律:\((f*g)*h=f*(g*h)\)
3.分配律:\(f*(g+h)=f*g+f*h\)
4.\(f*\varepsilon=f\)\(\varepsilon\) 即狄利克雷卷积的单位元。(其中,\(\varepsilon (n)=[n=1]\)

莫比乌斯函数

定义
\(n=\prod \limits _{i=1}^k p_i^{c_i}\)\(p_i\) 是质数) ,
\(\mu(n)= \begin{cases} 1&n=1\\ (-1)^k&c_i=1\\ 0& \text{otherwise} \end{cases}\)
性质

  1. \(\sum_{d|n} \mu(d)=\varepsilon(n)\)
  2. \([\gcd(i,j)=1] \Longleftrightarrow \sum \limits_{d|gcd(i,j)} \mu(d)\)

莫比乌斯反演

式子
\(f(n),g(n)\) 为两个数论函数,则
\(f(n)=\sum_{d|n} g(d) \Rightarrow g(n)=\sum_{d|n} \mu(d) f(\frac{n}{d})\)
\(f(n)=\sum_{n|d} g(d) \Rightarrow g(n)=\sum_{n|d} \mu(\frac{d}{n}) f(d)\)
证明
以第一个式子为例。
\(\sum \limits_{d|n} \mu(d) f(\frac{n}{d}) = \sum \limits_{d|n} \mu(d) \sum \limits_{k|\frac{n}{d}} g(k) = \sum \limits_{k|n} g(k) \sum \limits_{d|\frac{n}{k}} \mu(d) = \sum \limits_{k|n} g(k) [\frac{n}{k}=1] = g(n)\)

例题

1
\(\sum \limits_{x=a}^b \sum \limits_{y=c}^d [\gcd(x,y)=k]\)
容斥后,问题转化为求 \(\sum \limits_{x=1}^n \sum \limits_{y=1}^m [\gcd(x,y)=k]\)
同时除以 \(k\) ,得到 \(\sum \limits_{x=1}^{\left\lfloor \frac{n}{k} \right\rfloor} \sum \limits_{y=1}^{\left\lfloor \frac{m}{k} \right\rfloor} [\gcd(i,j)=1]\)
根据前面莫比乌斯函数的性质,得到 \(\sum \limits_{x=1}^{\left\lfloor \frac{n}{k} \right\rfloor} \sum \limits_{y=1}^{\left\lfloor \frac{m}{k} \right\rfloor} \sum \limits_{d|\gcd(i,j)} \mu(d)\)
变换求和顺序, \(\sum \limits_{d=1}^{min(n,m)} \mu(d) \sum \limits_{x=1}^{\left\lfloor \frac{n}{k} \right\rfloor} [d|x] \sum \limits_{y=1}^{\left\lfloor \frac{m}{k} \right\rfloor} [d|y]\)
\(1\) ~ \(n\)\(d\) 的倍数有 \(\left\lfloor \frac{n}{d} \right\rfloor\) 个,得到 \(\sum \limits_{d=1}^{min(n,m)} \mu(d) \left\lfloor \frac{n}{kd} \right\rfloor \left\lfloor \frac{m}{kd} \right\rfloor\)
数论分块求解即可。

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int N=5e4+10;
int cnt,p[N],mu[N],f[N];
int T,a,b,c,d,k;
bool flag[N];
int MIN(int x,int y)
{
	return x<y?x:y;
}
void O()
{
	mu[1]=1;
	for(int i=2;i<N;i++)
	{
		if(!flag[i]) p[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*p[j]<N;j++)
		{
			flag[i*p[j]]=1;
			if(i%p[j]==0)
			{
				mu[i*p[j]]=0;
				break;
			}
			mu[i*p[j]]=-mu[i];
		}
	}
	for(int i=1;i<N;i++) f[i]=f[i-1]+mu[i];
}
int calc(int n,int m)
{
	int l=0,r=0,ans=0;
	while(l<=MIN(n,m))
	{
		l=r+1;
		if(n/l==0||m/l==0) r=MIN(n,m);
		else r=MIN(n/(n/l),m/(m/l));
		ans+=(n/l)*(m/l)*(f[r]-f[l-1]);
	}
	return ans;
}
signed main()
{
	O();
	scanf("%lld",&T);
	while(T--)
	{
		scanf("%lld%lld%lld%lld%lld",&a,&b,&c,&d,&k);
		printf("%lld\n",calc(b/k,d/k)-calc((a-1)/k,d/k)-calc(b/k,(c-1)/k)+calc((a-1)/k,(c-1)/k));
	}
	return 0;
}

2
\(\sum \limits_{i=1}^n \operatorname{lcm}(i,n)\)
原式即 \(\sum \limits_{i=1}^n \frac{i \times n}{\gcd(i,n)}\)
将原式复制一遍,颠倒顺序,并且提出 \(n\) 一项,得 \(\frac{1}{2} \times (\sum \limits_{i=1}^{n-1} \frac{i \times n}{\gcd(i,n)}+\sum \limits_{i=n-1}^1 \frac{i \times n}{\gcd(i,n)})+n\)
根据 \(\gcd(i,n)=\gcd(n-i,n)\) ,得 \(\frac{1}{2} \times (\sum \limits_{i=1}^{n-1} \frac{i \times n}{\gcd(i,n)}+\sum \limits_{i=n-1}^1 \frac{i \times n}{\gcd(n-i,n)})+n\)
合并分母相同的项, \(\frac{1}{2} \times \sum \limits_{i=1}^{n-1} \frac{n^2}{\gcd(i,n)}+n\)
把一个 \(n\) 合回来, \(\frac{1}{2} \times \sum \limits_{i=1}^{n} \frac{n^2}{\gcd(i,n)}+ \frac{n}{2}\)
考虑枚举 gcd ,要统计 \(\gcd(i,n)=d\) 的个数。
\(\gcd(i,n)=d\) 时, \(\gcd(\frac{i}{d},\frac{n}{d})=1\) ,所以 \(\gcd(i,n)=d\) 的个数为 \(\varphi(\frac{n}{d})\) 个。
得到 \(\frac{1}{2} \times \sum \limits_{d|n} \frac{n^2*\varphi(\frac{n}{d})}{d}+\frac{n}{2}\)
\(\frac{n^2*\varphi(\frac{n}{d})}{d}\) 中提个 \(n\) 出来,再设 \(d'=\frac{n}{d}\)
得到 \(\frac{1}{2}n \times (\sum \limits_{d'|n} d' \times \varphi(d')+1)\)
发现 \(\sum \limits_{d'|n} d' \times \varphi(d')\) 为积性函数,直接筛即可。

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int N=1e6+10;
int T,n,f[N],p[N],cnt;
bool flag[N];
void O()
{
	flag[0]=1,flag[1]=1,f[1]=1;
	for(int i=2;i<N;i++)
	{
		if(!flag[i]) p[++cnt]=i,f[i]=i*(i-1)+1;
		for(int j=1;j<=cnt&&i*p[j]<N;j++)
		{
			flag[i*p[j]]=1;
			if(i%p[j]==0)
			{
				f[i*p[j]]=f[i]+(f[i]-f[i/p[j]])*p[j]*p[j];
				break;
			}
			f[i*p[j]]=f[i]*f[p[j]];
		}
	}
}
signed main()
{
	O();
	scanf("%lld",&T);
	while(T--)
	{
		scanf("%lld",&n);
		printf("%lld\n",n*(f[n]+1)/2);
	}
	return 0;
}

3
\(\sum \limits_{i=1}^n \sum \limits_{j=1}^m \operatorname{lcm}(i,j)\)
显然,原式即 \(\sum \limits_{i=1}^n \sum \limits_{j=1}^m \frac{i \cdot j}{\gcd(i,j)}\)
枚举 \(\gcd\) ,两数除以 \(\gcd\) 后得到的数互质,得 \(\sum \limits_{k=1}^n k \cdot \sum \limits_{i=1}^{\left\lfloor \frac{n}{k} \right\rfloor} \sum \limits_{j=1}^{\left\lfloor \frac{m}{k} \right\rfloor} [\gcd(i,j)=1] i \cdot j\)
考虑把后面的式子拿出来计算,记 \(\operatorname{sum}(n,m)=\sum \limits_{i=1}^n \sum \limits_{j=1}^m [\gcd(i,j)=1] i \cdot j\)
接下来化简这个式子。利用莫比乌斯函数的性质,同时枚举 \(\gcd\) ,得到 \(\sum \limits_{k=1}^n \sum \limits_{i=1}^n \sum \limits_{j=1}^m [k|i][k|j]\mu(d) \cdot i \cdot j\)
把后面的部分除以 \(k\) ,得到 \(\sum \limits_{k=1}^n \mu(k) \cdot k^2 \cdot \sum \limits_{i=1}^{\left\lfloor \frac{n}{k} \right\rfloor} \sum \limits_{j=1}^{\left\lfloor \frac{m}{k} \right\rfloor} i \cdot j\)
发现式子的前半段可以前缀和预处理,后半段可以直接算,合并的部分用数论分块即可。
\(\operatorname{sum}\) 代回原式, \(\sum \limits_{k=1}^n k \cdot \operatorname{sum}(\left\lfloor \frac{n}{k} \right\rfloor,\left\lfloor \frac{m}{k} \right\rfloor)\)
发现这个式子依然可以用数论分块求解。

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int N=1e7+10;
const int P=20101009;
int cnt,p[N],mu[N],f[N];
int n,m;
bool flag[N];
int MIN(int x,int y)
{
	return x<y?x:y;
}
void O()
{
	mu[1]=1;
	for(int i=2;i<N;i++)
	{
		if(!flag[i]) p[++cnt]=i,mu[i]=-1;
		for(int j=1;j<=cnt&&i*p[j]<N;j++)
		{
			flag[i*p[j]]=1;
			if(i%p[j]==0)
			{
				mu[i*p[j]]=0;
				break;
			}
			mu[i*p[j]]=-mu[i];
		}
	}
	for(int i=1;i<N;i++) f[i]=(f[i-1]+(mu[i]+P)%P*i%P*i%P)%P;
}
int sum(int n,int m)
{
	return (n*(n+1)/2%P)*(m*(m+1)/2%P)%P;
}
int calc(int n,int m)
{
	int l=0,r=0,ans=0;
	while(l<=MIN(n,m))
	{
		l=r+1;
		if(n/l==0||m/l==0) r=MIN(n,m);
		else r=MIN(n/(n/l),m/(m/l));
		ans=(ans+(f[r]-f[l-1]+P)%P*sum(n/l,m/l)%P)%P;
	}
	return ans;
}
int CALC(int n,int m)
{
	int l=0,r=0,ans=0;
	while(l<=MIN(n,m))
	{
		l=r+1;
		if(n/l==0||m/l==0) r=MIN(n,m);
		else r=MIN(n/(n/l),m/(m/l));
		ans=(ans+calc(n/l,m/l)*((l+r)*(r-l+1)/2%P)%P)%P;
	}
	return ans;
}
signed main()
{
	O();
	scanf("%lld%lld",&n,&m);
	printf("%lld",CALC(n,m));
	return 0;
}

4
\(\sum \limits_{i=1}^n \sum \limits_{j=1}^m d(i \cdot j)\) ,其中 \(d\) 为约数个数函数。
首先, \(d\) 函数有一个性质, \(d(i \cdot j)=\sum \limits_{x|i} \sum \limits_{y|j} [\gcd(x,y)=1]\)
推一推,
\(d(i \cdot j)=\sum \limits_{x|i} \sum \limits_{y|j} [\gcd(x,y)=1]\)
\(\ \ \ \ \ \ \ \ \ \ \ =\sum \limits_{x|i} \sum \limits_{y|j} \sum \limits_{k|\gcd(x,y)} \mu(k)\)
\(\ \ \ \ \ \ \ \ \ \ \ =\sum \limits_{k=1}^{min(i,j)} \sum \limits_{x|i} \sum \limits_{y|j} [k|\gcd(x,y)] \cdot \mu(k)\)
\(\ \ \ \ \ \ \ \ \ \ \ =\sum \limits_{k|i,k|j} \mu(k) \sum \limits_{x|i} \sum \limits_{y|j} [k|\gcd(x,y)]\)
\(\ \ \ \ \ \ \ \ \ \ \ =\sum \limits_{k|i,k|j} \mu(k) \sum \limits_{x|\left\lfloor \frac{i}{k} \right\rfloor} \sum \limits_{y|\left\lfloor \frac{j}{k} \right\rfloor} 1\)
\(\ \ \ \ \ \ \ \ \ \ \ =\sum \limits_{k|i,k|j} \mu(k) d(\left\lfloor \frac{i}{k} \right\rfloor) d(\left\lfloor \frac{j}{k} \right\rfloor)\) .
把这个式子代回原式,
\(\ \ \ \sum \limits_{i=1}^n \sum \limits_{j=1}^m d(i \cdot j)\)
\(=\sum \limits_{i=1}^n \sum \limits_{j=1}^m \sum \limits_{k|i,k|j} \mu(k) d(\left\lfloor \frac{i}{k} \right\rfloor) d(\left\lfloor \frac{j}{k} \right\rfloor)\)
\(=\sum \limits_{k=1}^{min(n,m)} \sum \limits_{i=1}^n \sum \limits_{j=1}^m [k|i][k|j]\mu(k) d(\left\lfloor \frac{i}{k} \right\rfloor) d(\left\lfloor \frac{j}{k} \right\rfloor)\)
\(=\sum \limits_{k=1}^{min(n,m)} \mu(k) \sum \limits_{i=1}^{\left\lfloor \frac{n}{k} \right\rfloor} d(i) \sum \limits_{j=1}^{\left\lfloor \frac{m}{k} \right\rfloor} d(j)\) .
发现每一部分均可前缀和预处理,用数论分块合并答案即可。

#include<iostream>
#include<cstdio>
#define int long long
using namespace std;
const int N=5e4+10;
int T,n,m,f[N],F[N];
int cnt,p[N],d[N],t[N],mu[N];
bool flag[N];
int MIN(int x,int y)
{
	return x<y?x:y;
}
void O()
{
	flag[0]=1,flag[1]=1;
	mu[1]=1,d[1]=1;
	for(int i=2;i<N;i++)
	{
		if(!flag[i]) p[++cnt]=i,mu[i]=-1,d[i]=2,t[i]=1;
		for(int j=1;j<=cnt&&i*p[j]<N;j++)
		{
			flag[i*p[j]]=1;
			if(i%p[j]==0)
			{
				mu[i*p[j]]=0;
				d[i*p[j]]=d[i]/(t[i]+1)*(t[i]+2);
				t[i*p[j]]=t[i]+1;
				break;
			}
			mu[i*p[j]]=-mu[i],d[i*p[j]]=d[i]*2,t[i*p[j]]=1;
		}
	}
	for(int i=1;i<N;i++) f[i]=f[i-1]+mu[i];
	for(int i=1;i<N;i++) F[i]=F[i-1]+d[i];
}
int calc(int n,int m)
{
	int l=0,r=0,ans=0;
	while(l<=MIN(n,m))
	{
		l=r+1;
		if(n/l==0||m/l==0) r=MIN(n,m);
		else r=MIN(n/(n/l),m/(m/l));
		ans+=(f[r]-f[l-1])*F[n/l]*F[m/l];
	}
	return ans;
}
signed main()
{
	O();
	scanf("%lld",&T);
	while(T--)
	{
		scanf("%lld%lld",&n,&m);
		printf("%lld\n",calc(n,m));
	}
	return 0;
}
posted @ 2021-01-04 10:59  BBD186587  阅读(77)  评论(0编辑  收藏  举报