【暖*墟】#数论# 莫比乌斯反演的学习与练习
2020-02-04 17:38
106 查看
莫比乌斯反演的应用范围
一些函数很难直接求值,而容易求出其倍数和或约数和,那么可以通过莫比乌斯反演求得原函数的值。
积性函数
定义:若 gcd(x,y)=1 ,且 f(xy)=f(x)f(y),则 f(n) 为积性函数。
性质:若 f(x) 和 g(x) 均为积性函数,则以下函数也为积性函数。
常见积性函数
Dirichlet 卷积
- Dirichlet 卷积满足交换律、结合律、分配律。
其中 ε 为 Dirichlet 卷积的单位元(任何函数卷 ε 都为其本身)。
莫比乌斯函数
其中最重要的性质就是
void get_mu(int n){
mu[1]=1; for(int i=2;i<=n;i++){
if(!vis[i]) primes[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&primes[j]*i<=n;j++){
vis[primes[j]*i]=1;
if(i%primes[j]==0) break;
else mu[i*primes[j]]=-mu[i]; } } }
莫比乌斯反演
- 公式可以进一步转化为:
相关习题练习
T1:【p3455】ZAP / 【p4450】双亲数
#include <cmath> #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector> #include <algorithm> #include <stack> #include <queue> using namespace std; typedef long long ll; typedef unsigned long long ull; //【p3455】ZAP // 求∑(i=1~n)∑(j=1~m)[gcd(x,y)=d] // 设f(d)为 gcd(i,j)=d 的个数,F(n)为 gcd(i,j)=d和d的倍数 的个数。 // 即:f(d)=∑(i=1~n)∑(j=1~m)[gcd(i,j)=d],F(n)=∑(n|d)f(d)=⌊N/n⌋⌊M/n⌋。 // 则可以得到:f(n)=∑(n|d) μ(⌊d/n⌋)*F(d)。 // 接下来的推导公式见:http://www.cnblogs.com/peng-ym/p/8652288.html const int N=10000019; bool vis ; int primes ,cnt=0,mu ,g ; ll sum ; void get_mu(int n){ mu[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]) primes[++cnt]=i,mu[i]=-1; for(int j=1;j<=cnt&&primes[j]*i<=n;j++){ vis[primes[j]*i]=1; if(i%primes[j]==0) break; else mu[i*primes[j]]=-mu[i]; } } for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i]; } int main(){ int T,n,m,d; cin>>T; get_mu(50000); while(T--){ scanf("%d%d%d",&n,&m,&d); n=n/d,m=m/d; ll ans=0; for(int l=1,r;l<=min(n,m);l=r+1){ r=min(n/(n/l),m/(m/l)); //整除分块 ans+=1LL*(n/l)*(m/l)*(sum[r]-sum[l-1]); } cout<<ans<<endl; //满足gcd(x,y)=d的(x,y)对数 } }【p3455】ZAP // 求 ∑(i=1~n)∑(j=1~m)[gcd(x,y)=d]
T2:【p2522】problem B
- ZAP+简单容斥原理(类似于二维前缀和的容斥):
ans=Ans((1,b),(1,d))−Ans((1,b),(1,c−1))−Ans((1,a−1),(1,d))+Ans((1,a−1),(1,c−1))
#include <cmath> #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector> #include <algorithm> #include <stack> #include <queue> using namespace std; typedef long long ll; typedef unsigned long long ull; //【p2522】problem B //'ZAP'的一般情况:求∑(i=a~b)∑(j=c~d)[gcd(x,y)=k] // 设f(d)为 gcd(i,j)=d 的个数,F(n)为 gcd(i,j)=d和d的倍数 的个数。 // 即:f(d)=∑(i=1~n)∑(j=1~m)[gcd(i,j)=d],F(n)=∑(n|d)f(d)=⌊N/n⌋⌊M/n⌋。 // 则可以得到:f(n)=∑(n|d) μ(⌊d/n⌋)*F(d)。 // ZAP+简单容斥原理即可(类似于二维前缀和的容斥): // ans=Ans((1,b),(1,d))−Ans((1,b),(1,c−1))−Ans((1,a−1),(1,d))+Ans((1,a−1),(1,c−1)) const int N=10000019; bool vis ; int primes ,cnt=0,mu ,k; ll sum ; void get_mu(int n){ mu[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]) primes[++cnt]=i,mu[i]=-1; for(int j=1;j<=cnt&&primes[j]*i<=n;j++){ vis[primes[j]*i]=1; if(i%primes[j]==0) break; else mu[i*primes[j]]=-mu[i]; } } for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i]; } ll calc(int n,int m){ n=n/k,m=m/k; ll ans=0; for(int l=1,r;l<=min(n,m);l=r+1){ r=min(n/(n/l),m/(m/l)); //整除分块 ans+=1LL*(n/l)*(m/l)*(sum[r]-sum[l-1]); } return ans; //1~n,1~m,满足gcd(x,y)=k的(x,y)对数 } int main(){ int T,a,b,c,d; cin>>T; get_mu(50000); while(T--){ scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); cout<<calc(b,d)-calc(b,c-1)-calc(a-1,d)+calc(a-1,c-1)<<endl; } }【p2522】problem B //'ZAP'的一般情况:求∑(i=a~b)∑(j=c~d)[gcd(x,y)=k]
T3:【p2257】YY的GCD
- 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x,y)为质数的(x,y)有多少对。
#include <cmath> #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector> #include <algorithm> #include <stack> #include <queue> using namespace std; typedef long long ll; typedef unsigned long long ull; //【p2257】YY的GCD // 给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对。 // ∑(i=1~n)∑(j=1~m)[gcd(x,y)=primes] // 设f(d)为 gcd(i,j)=d 的个数,F(n)为 gcd(i,j)=d和d的倍数 的个数。 // 即:f(d)=∑(i=1~n)∑(j=1~m)[gcd(i,j)=d],F(n)=∑(n|d)f(d)=⌊N/n⌋⌊M/n⌋。 // 则可以得到:f(n)=∑(n|d) μ(⌊d/n⌋)*F(d)。 // 接下来的推导公式见:http://www.cnblogs.com/peng-ym/p/8652288.html const int N=10000019; bool vis ; int primes ,cnt=0,mu ,g ; ll sum ; void get_mu(int n){ mu[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]) primes[++cnt]=i,mu[i]=-1; for(int j=1;j<=cnt&&primes[j]*i<=n;j++){ vis[primes[j]*i]=1; if(i%primes[j]==0) break; else mu[i*primes[j]]=-mu[i]; } } for(int j=1;j<=cnt;j++) for(int i=1;i*primes[j]<=n;i++) g[i*primes[j]]+=mu[i]; for(int i=1;i<=n;i++) sum[i]=sum[i-1]+(ll)g[i]; } int main(){ int T,n,m; cin>>T; get_mu(10000000); while(T--){ scanf("%d%d",&n,&m); if(n>m) swap(n,m); ll ans=0; for(int l=1,r;l<=n;l=r+1){ r=min(n/(n/l),m/(m/l)); //整除分块 ans+=1LL*(n/l)*(m/l)*(sum[r]-sum[l-1]); } cout<<ans<<endl; //满足gcd(x,y)为质数的(x,y)对数 } }【p2257】YY的GCD // 求 ∑(i=1~n)∑(j=1~m)[gcd(x,y)=primes]
T4:【p3327】约数个数和
#include <cmath> #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector> #include <algorithm> #include <stack> #include <queue> using namespace std; typedef long long ll; typedef unsigned long long ull; //【p3327】约数个数和 // 设d(x)为x的约数个数,求 ∑(i=1~n)∑(j=1~m)d(i*j) // 约数个数的公式:d(i*j)=∑(x|i)∑(y|j)[gcd(x,y)=1]。 // 设f(d)为 gcd(i,j)=d 的个数,F(n)为 gcd(i,j)=d和d的倍数 的个数。 // 即:f(d)=∑(i=1~n)∑(j=1~m)[gcd(i,j)=d],F(n)=∑(n|d)f(d)=⌊N/n⌋⌊M/n⌋。 // 则可以得到:f(n)=∑(n|d) μ(⌊d/n⌋)*F(d)。 // Ans=∑(i=1~n)∑(j=1~m)∑(x|i)∑(y|j)[gcd(x,y)=1]。 // 根据公式推出:Ans=∑(i=1~n)∑(j=1~m)∑(x|i)∑(y|j)∑(d|gcd(x,y))μ(d)。 // 后续推导见:https://www.cnblogs.com/peng-ym/p/8667321.html。 const int N=10000019; bool vis ; int primes ,cnt=0,mu ,g ; ll sum ; void get_mu(int n){ mu[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]) primes[++cnt]=i,mu[i]=-1; for(int j=1;j<=cnt&&primes[j]*i<=n;j++) { vis[primes[j]*i]=1; if(i%primes[j]==0) break; else mu[i*primes[j]]=-mu[i]; } } for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i]; for(int i=1;i<=n;i++){ ll anss=0; for(int l=1,r;l<=i;l=r+1) r=(i/(i/l)),anss+=1LL*(r-l+1)*(i/l); g[i]=anss; } } int main(){ int T,n,m; cin>>T; get_mu(50000); while(T--){ scanf("%d%d",&n,&m); ll ans=0; for(int l=1,r;l<=min(n,m);l=r+1){ r=min(n/(n/l),m/(m/l)); //整除分块 ans+=1LL*g[n/l]*1LL*g[m/l]*(sum[r]-sum[l-1]); } cout<<ans<<endl; //满足gcd(x,y)=d的(x,y)对数 } }【p3327】约数个数和 // 设d(x)为x的约数个数,求 ∑(i=1~n)∑(j=1~m)d(i*j)。
- 约数个数的公式:d(i*j)=∑(x|i)∑(y|j)[gcd(x,y)=1]
转载于:https://www.cnblogs.com/FloraLOVERyuuji/p/10539217.html
- 点赞
- 收藏
- 分享
- 文章举报
相关文章推荐
- BZOJ 4176: Lucas的数论 莫比乌斯反演 杜教筛
- [持续更新]莫比乌斯反演、杜教筛等数论变换中的小技巧
- 【BZOJ4176】Lucas的数论 莫比乌斯反演
- [2012集训队互测]JZPKIL - 生成函数,伯努利数,数论,莫比乌斯反演,狄利克雷卷积
- [hdu 5072]Coprime 数论-莫比乌斯反演
- [数论][莫队][莫比乌斯反演] hdu 4676 Sum Of Gcd
- [容斥原理与莫比乌斯反演][学习笔记]
- 算法学习:莫比乌斯反演
- BZOJ4652 [Noi2016]循环之美 【数论 + 莫比乌斯反演 + 杜教筛】
- HDU 1695 GCD (莫比乌斯反演入门学习小结)
- bzoj 4176: Lucas的数论【莫比乌斯反演+杜教筛】
- 学习笔记 | 反演 | 二项式反演 | 莫比乌斯反演 | 狄利克雷卷积 |容斥 | 未完待更 | 在更
- 莫比乌斯反演的学习
- [莫比乌斯反演 高斯消元 数学技巧] BZOJ 3601 一个人的数论
- bzoj 4174 tty的求助 数论 莫比乌斯反演
- 数论变换入门 莫比乌斯反演 杜教筛
- 莫比乌斯反演学习笔记
- 【数论】【枚举】【莫比乌斯反演】【线性筛】bzoj2818 Gcd
- 【数论】Mobius反演学习笔记
- HDU1695 GCD 数论之 莫比乌斯反演