【数论】莫比乌斯反演巩固1

前言

这里需要对莫反有一些基础
不会的可以点这里

洛谷P3455

题意:
给定 a , b , d a,b,d a,b,d
∑ x = 1 a ∑ y = 1 b [ gcd ⁡ ( x , y ) = d ] \sum_{x=1}^a\sum_{y=1}^b[\gcd(x,y)=d] x=1ay=1b[gcd(x,y)=d]
1 ≤ n ≤ 5 × 1 0 4 1\leq n\leq5\times 10^4 1n5×104 1 ≤ d ≤ a , b ≤ 5 × 1 0 4 1 \leq d \leq a,b \leq 5 \times 10^4 1da,b5×104
按照套路:
∑ x = 1 a ∑ y = 1 b [ gcd ⁡ ( x , y ) = d ] \sum_{x=1}^a\sum_{y=1}^b[\gcd(x,y)=d] x=1ay=1b[gcd(x,y)=d]
= ∑ x = 1 a d ∑ y = 1 b d [ gcd ⁡ ( x , y ) = 1 ] =\sum_{x=1}^{\frac{a}{d}}\sum_{y=1}^{\frac{b}{d}}[\gcd(x,y)=1] =x=1day=1db[gcd(x,y)=1]
= ∑ x = 1 a d ∑ y = 1 b d ∑ k ∣ gcd ⁡ ( x , y ) μ ( k ) =\sum_{x=1}^{\frac{a}{d}}\sum_{y=1}^{\frac{b}{d}}\sum_{k|\gcd(x,y)}\mu(k) =x=1day=1dbkgcd(x,y)μ(k)
= ∑ x = 1 a d ∑ y = 1 b d ∑ k = 1 μ ( k ) [ k ∣ gcd ⁡ ( x , y ) ] =\sum_{x=1}^{\frac{a}{d}}\sum_{y=1}^{\frac{b}{d}}\sum_{k=1}\mu(k)[k|\gcd(x,y)] =x=1day=1dbk=1μ(k)[kgcd(x,y)]
= ∑ k = 1 min ⁡ ( a d , b d ) μ ( k ) ∑ x = 1 a d ∑ y = 1 b d [ k ∣ gcd ⁡ ( x , y ) ] =\sum_{k=1}^{\min(\frac{a}{d},\frac{b}{d})}\mu(k)\sum_{x=1}^{\frac{a}{d}}\sum_{y=1}^{\frac{b}{d}}[k|\gcd(x,y)] =k=1min(da,db)μ(k)x=1day=1db[kgcd(x,y)]
= ∑ k = 1 min ⁡ ( a d , b d ) μ ( k ) ⌊ a d k ⌋ ⌊ b d k ⌋ =\sum_{k=1}^{\min(\frac{a}{d},\frac{b}{d})}\mu(k)\left\lfloor\frac{\frac{a}{d}}{k}\right\rfloor\left\lfloor\frac{\frac{b}{d}}{k}\right\rfloor =k=1min(da,db)μ(k)kdakdb

数论分块解决即可。
Code:

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=2e6+1,M=2e6+1;
int t,n,m,k,ans=0;
struct fy{
	int prv[N],cnt,mu[N],sum[N];
	bool pr[N];
	void ola(int x){
		pr[1]=mu[1]=1;
		for(int i=2;i<=x;i++){
			if(!pr[i])
				prv[++cnt]=i,mu[i]=-1;
			for(int j=1;j<=cnt&&i*prv[j]<=x;j++){
				int u=i*prv[j];
				pr[u]=1;
				if(i%prv[j]==0){
					mu[u]=0;
					break;
				}
				else{
					mu[u]=-mu[i];
				}
			}
		}
		for(int i=1;i<=x;i++)
			sum[i]=sum[i-1]+mu[i];
			
	}
}A;
signed main(){
	IOS;
	A.ola(N-1);
	cin>>t;
	while(t--){
		cin>>n>>m>>k;
		n/=k,m/=k;
		ans=0;
		for(int l=1,r;l<=min(n,m);l=r+1){
			r=min(n/(n/l),m/(m/l));
			ans+=(A.sum[r]-A.sum[l-1])*(n/l)*(m/l);
		}
		cout<<ans<<"\n";
	}
	return 0;
}

洛谷P1829

题意:给定 n , m n,m n,m,求 ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) \sum_{i=1}^n\sum_{j=1}^m lcm(i,j) i=1nj=1mlcm(i,j)
1 ≤ n , m ≤ 1 0 7 1\leq n,m\leq 10^7 1n,m107

∑ i = 1 n ∑ j = 1 m l c m ( i , j ) \sum_{i=1}^n\sum_{j=1}^m lcm(i,j) i=1nj=1mlcm(i,j)
= ∑ i = 1 n ∑ j = 1 m i j gcd ⁡ ( i , j ) =\sum_{i=1}^n\sum_{j=1}^m\frac{ij}{\gcd(i,j)} =i=1nj=1mgcd(i,j)ij
o = min ⁡ ( n , m ) o=\min(n,m) o=min(n,m)
= ∑ d = 1 o ∑ i = 1 n ∑ j = 1 m [ gcd ⁡ ( i , j ) = d ] i j d =\sum_{d=1}^o\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d]\frac{ij}{d} =d=1oi=1nj=1m[gcd(i,j)=d]dij
a = ⌊ n d ⌋ , b = ⌊ m d ⌋ , c = min ⁡ ( a , b ) a=\left\lfloor\frac{n}{d}\right\rfloor,b=\left\lfloor\frac{m}{d}\right\rfloor,c=\min(a,b) a=dn,b=dm,c=min(a,b)
= ∑ d = 1 o d ∑ i = 1 a ∑ j = 1 b [ gcd ⁡ ( i , j ) = 1 ] i j =\sum_{d=1}^o d\sum_{i=1}^a\sum_{j=1}^b[\gcd(i,j)=1]ij =d=1odi=1aj=1b[gcd(i,j)=1]ij
= ∑ d = 1 o d ∑ i = 1 a ∑ j = 1 b i j ∑ k ∣ gcd ⁡ ( i , j ) μ ( k ) =\sum_{d=1}^o d\sum_{i=1}^a\sum_{j=1}^bij\sum_{k|\gcd(i,j)}\mu(k) =d=1odi=1aj=1bijkgcd(i,j)μ(k)
= ∑ d = 1 o d ∑ k = 1 c μ ( k ) ∑ i = 1 a ∑ j = 1 b i j [ k ∣ gcd ⁡ ( i , j ) ] =\sum_{d=1}^o d\sum_{k=1}^c\mu(k)\sum_{i=1}^a\sum_{j=1}^bij[k|\gcd(i,j)] =d=1odk=1cμ(k)i=1aj=1bij[kgcd(i,j)]
= ∑ d = 1 o d ∑ k = 1 c μ ( k ) ∑ i = 1 ⌊ a k ⌋ ∑ j = 1 ⌊ b k ⌋ i k ⋅ j k =\sum_{d=1}^o d\sum_{k=1}^c\mu(k)\sum_{i=1}^{\left\lfloor\frac{a}{k}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{b}{k}\right\rfloor}ik\cdot jk =d=1odk=1cμ(k)i=1kaj=1kbikjk
= ∑ d = 1 o d ∑ k = 1 c μ ( k ) ∑ i = 1 ⌊ a k ⌋ ∑ j = 1 ⌊ b k ⌋ i j k 2 =\sum_{d=1}^o d\sum_{k=1}^c\mu(k)\sum_{i=1}^{\left\lfloor\frac{a}{k}\right\rfloor}\sum_{j=1}^{\left\lfloor\frac{b}{k}\right\rfloor}ijk^2 =d=1odk=1cμ(k)i=1kaj=1kbijk2
= ∑ d = 1 o d ∑ k = 1 c μ ( k ) k 2 ∑ i = 1 ⌊ a k ⌋ i ∑ j = 1 ⌊ b k ⌋ j =\sum_{d=1}^o d\sum_{k=1}^c\mu(k)k^2\sum_{i=1}^{\left\lfloor\frac{a}{k}\right\rfloor}i\sum_{j=1}^{\left\lfloor\frac{b}{k}\right\rfloor}j =d=1odk=1cμ(k)k2i=1kaij=1kbj
s u m ( n ) = ∑ i = 1 n i , T = k d sum(n)=\sum_{i=1}^ni,T=kd sum(n)=i=1ni,T=kd
= ∑ d = 1 o d ∑ k = 1 c μ ( k ) k 2 s u m ( ⌊ a k ⌋ ) s u m ( ⌊ b k ⌋ ) =\sum_{d=1}^o d\sum_{k=1}^c\mu(k)k^2sum(\left\lfloor\frac{a}{k}\right\rfloor)sum(\left\lfloor\frac{b}{k}\right\rfloor) =d=1odk=1cμ(k)k2sum(ka)sum(kb)
= ∑ d = 1 o d ∑ k = 1 min ⁡ ( ⌊ n d ⌋ , ⌊ m d ⌋ ) μ ( k ) k 2 s u m ( ⌊ n k d ⌋ ) s u m ( ⌊ m k d ⌋ ) =\sum_{d=1}^o d\sum_{k=1}^{\min(\left\lfloor\frac{n}{d}\right\rfloor,\left\lfloor\frac{m}{d}\right\rfloor)}\mu(k)k^2sum(\left\lfloor\frac{n}{kd}\right\rfloor)sum(\left\lfloor\frac{m}{kd}\right\rfloor) =d=1odk=1min(dn,dm)μ(k)k2sum(kdn)sum(kdm)
= ∑ T = 1 o s u m ( n T ) s u m ( m T ) T ∑ d ∣ T d μ ( d ) =\sum_{T=1}^osum(\frac{n}{T})sum(\frac{m}{T})T\sum_{d|T}d\mu(d) =T=1osum(Tn)sum(Tm)TdTdμ(d)
g ( n ) = ∑ d ∣ n d μ ( d ) g(n)=\sum_{d|n}d\mu(d) g(n)=dndμ(d)
= ∑ T = 1 o s u m ( n T ) s u m ( m T ) T g ( T ) =\sum_{T=1}^osum(\frac{n}{T})sum(\frac{m}{T})Tg(T) =T=1osum(Tn)sum(Tm)Tg(T)

考虑线性筛出 g ( n ) g(n) g(n)
还可以用数论分块优化,但也可以不用。
Code:

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=1e7+1,mod=20101009;
int t,n,m,k;
struct fy{
	int prv[N],cnt,g[N],s[N];
	bool pr[N];
	void ola(int x){
		pr[1]=g[1]=1;
		for(int i=2;i<=x;i++){
			if(!pr[i])
				prv[++cnt]=i,g[i]=(1-i+mod)%mod;
			for(int j=1;j<=cnt&&i*prv[j]<=x;j++){
				int u=i*prv[j];
				pr[u]=1;
				if(i%prv[j]==0){
					g[u]=g[i];
					break;
				}
				else{
					g[u]=g[i]*g[prv[j]]%mod;
				}
			}
		}
	}
	void getsum(int x){
		for(int i=1;i<=x;i++)
			s[i]=(s[i-1]+i)%mod;
	}
}A;
signed main(){
	IOS;
	A.ola(N-1);
	A.getsum(N-1);
	cin>>n>>m;
	int ans=0;
	for(int i=1;i<=min(n,m);i++){
		ans+=A.s[n/i]*A.s[m/i]%mod*i%mod*A.g[i]%mod;
		ans%=mod;
	}
	cout<<ans;
	return 0;
}
#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=1e7+1,mod=20101009;
int t,n,m,k;
struct fy{
	int prv[N],cnt,g[N],s[N];
	bool pr[N];
	void ola(int x){
		pr[1]=g[1]=1;
		for(int i=2;i<=x;i++){
			if(!pr[i])
				prv[++cnt]=i,g[i]=(1-i+mod)%mod;
			for(int j=1;j<=cnt&&i*prv[j]<=x;j++){
				int u=i*prv[j];
				pr[u]=1;
				if(i%prv[j]==0){
					g[u]=g[i];
					break;
				}
				else{
					g[u]=g[i]*g[prv[j]]%mod;
				}
			}
		}
	}
	void getsum(int x){
		for(int i=1;i<=x;i++)
			s[i]=(s[i-1]+i)%mod,g[i]=(i*g[i]+g[i-1])%mod;
	}
}A;
signed main(){
	IOS;
	A.ola(N-1);
	A.getsum(N-1);
	cin>>n>>m;
	int ans=0;
	for(int l=1,r;l<=min(n,m);l=r+1){
		r=min(n/(n/l),m/(m/l));
		ans+=A.s[n/l]*A.s[m/l]%mod*((A.g[r]-A.g[l-1]+mod)%mod)%mod;
		ans%=mod;
	}
	cout<<ans;
	return 0;
}

洛谷P4449

题意:给定 n , m , k n,m,k n,m,k,求 ∑ i = 1 n ∑ j = 1 m gcd ⁡ ( i , j ) k \sum_{i=1}^n\sum_{j=1}^m\gcd(i,j)^k i=1nj=1mgcd(i,j)k
1 ≤ T ≤ 2 × 1 0 3 , 1 ≤ n , m , k ≤ 5 × 1 0 6 1 \leq T \leq 2 \times 10^3,1\leq n, m, k \leq 5\times10^6 1T2×103,1n,m,k5×106
∑ i = 1 n ∑ j = 1 m gcd ⁡ ( i , j ) k \sum_{i=1}^n\sum_{j=1}^m\gcd(i,j)^k i=1nj=1mgcd(i,j)k
a , b , c , o a,b,c,o a,b,c,o的含义同上文。
= ∑ d = 1 o d k ∑ i = 1 n ∑ j = 1 m [ gcd ⁡ ( i , j ) = d ] =\sum_{d=1}^od^k\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=d] =d=1odki=1nj=1m[gcd(i,j)=d]
= ∑ d = 1 o d k ∑ p = 1 c μ ( p ) ⌊ a p ⌋ ⌊ b p ⌋ =\sum_{d=1}^od^k\sum_{p=1}^c\mu(p)\left\lfloor\frac{a}{p}\right\rfloor\left\lfloor\frac{b}{p}\right\rfloor =d=1odkp=1cμ(p)papb
T = d p T=dp T=dp
= ∑ d = 1 o d k ∑ p = 1 c μ ( p ) ⌊ n T ⌋ ⌊ n T ⌋ =\sum_{d=1}^od^k\sum_{p=1}^c\mu(p)\left\lfloor\frac{n}{T}\right\rfloor\left\lfloor\frac{n}{T}\right\rfloor =d=1odkp=1cμ(p)TnTn
= ∑ T = 1 o ⌊ n T ⌋ ⌊ n T ⌋ ∑ d ∣ T d k μ ( T d ) =\sum_{T=1}^o\left\lfloor\frac{n}{T}\right\rfloor\left\lfloor\frac{n}{T}\right\rfloor\sum_{d|T}d^k\mu(\frac{T}{d}) =T=1oTnTndTdkμ(dT)

就跟上一题一样了,线性筛+数论分块。
Code:

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL)
using namespace std;
const int N=5e6+1,mod=1e9+7;
int t,n,m,k;
struct fy{
	int prv[N],cnt,g[N],s[N];
	bool pr[N];
	inline int qmi(int x,int y){
		int res=1;
		while(y>0){
			if(y&1)
				res=res*x%mod;
			x=x*x%mod,y>>=1;
		}
		return res;
	}
	void ola(int x){
		pr[1]=g[1]=1;
		for(int i=2;i<=x;i++){
			if(!pr[i])
				prv[++cnt]=i,g[i]=(qmi(i,k)-1+mod)%mod;
			for(int j=1;j<=cnt&&i*prv[j]<=x;j++){
				int u=i*prv[j];
				pr[u]=1;
				if(i%prv[j]==0){
					g[u]=g[i]*qmi(prv[j],k)%mod;
					break;
				}
				else{
					g[u]=g[i]*g[prv[j]]%mod;
				}
			}
		}
	}
	void getsum(int x){
		for(int i=1;i<=x;i++)
			g[i]=(g[i]+g[i-1])%mod;
	}
}A;
signed main(){
	IOS;
	cin>>t>>k;
	A.ola(N-1);
	A.getsum(N-1);
	while(t--){
		cin>>n>>m;
		int ans=0;
		for(int l=1,r;l<=min(n,m);l=r+1){
			r=min(n/(n/l),m/(m/l));
			ans+=(n/l)*(m/l)%mod*((A.g[r]-A.g[l-1]+mod)%mod)%mod;
			ans%=mod;
		}
		cout<<ans<<"\n";
	}
	return 0;
}
  • 22
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值