初涉莫比乌斯反演(附带例题)
什么是莫比乌斯反演
关于莫比乌斯反演
莫比乌斯反演,又称懵逼钨丝繁衍,是一种看了就一脸懵逼的东西。
好吧好吧,严肃点。(不过因为本蒟蒻真的很懵逼,所以错误之处请大神指出)
莫比乌斯反演就是下面这个式子:
如果存在函数F(x)和f(x),满足
F(n)=∑d∣nf(d)F(n)=\sum_{d|n} f(d)F(n)=d∣n∑f(d)
那么就有:
f(n)=∑d∣nμ(d)F(nd)f(n)=\sum_{d|n} \mu(d)F(\frac{n}{d})f(n)=d∣n∑μ(d)F(dn)
或者如果F(x)和f(x)满足:
F(n)=∑n∣df(d)F(n)=\sum_{n|d}f(d)F(n)=n∣d∑f(d)
那么:
f(n)=∑n∣dμ(dn)F(d)f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d)f(n)=n∣d∑μ(nd)F(d)
其中μ()\mu()μ()函数是莫比乌斯函数,定义是:
如果d=1d=1d=1 , μ(d)=1\mu(d)=1μ(d)=1
如果ddd为互异质数p1p_1p1,p2p_2p2…pkp_kpk的乘积,则μ(d)=(−1)k\mu(d)=(-1)^kμ(d)=(−1)k
否则,μ(d)=0\mu(d)=0μ(d)=0
所以线性筛莫比乌斯函数往后看,几乎每段代码里都有。
两条性质
好了,现在补充两条 (我不会证,不过脑补一下就好了吧的) 性质:
1.如果n>1n>1n>1且nnn为正整数,则有:
∑d∣nμ(d)=0\sum_{d|n}\mu(d)=0d∣n∑μ(d)=0
如果n=1n=1n=1则上式为1.
2.对于任意正整数nnn均有:
∑d∣nμ(d)d=ϕ(n)n\sum_{d|n}\frac{\mu(d)}{d}=\frac{\phi(n)}{n}d∣n∑dμ(d)=nϕ(n)
证明莫比乌斯反演
有了上面两条 我不会证的 性质之后,我们就可以证一下莫比乌斯反演了。
由F(x)函数的定义可以得到:
∑d∣nμ(d)F(nd)=∑d∣nμ(d)∑d′∣ndf(d′)\sum_{d|n}\mu(d)F(\frac{n}{d})=\sum_{d|n}\mu(d)\sum_{d'|\frac{n}{d}}f(d')d∣n∑μ(d)F(dn)=d∣n∑μ(d)d′∣dn∑f(d′)
接下来我们让nd=kd′\frac{n}{d}=kd'dn=kd′,那么d=nkd′d=\frac{n}{kd'}d=kd′n,所以就有d∣nd′d|\frac{n}{d'}d∣d′n,而每个f(d′)f(d')f(d′)一定会和一个μ(d)\mu(d)μ(d)乘一次,所以:
∑d∣nμ(d)∑d′∣ndf(d′)=∑d′∣nf(d′)∑d∣nd′μ(d)\sum_{d|n}\mu(d)\sum_{d'|\frac{n}{d}}f(d')=\sum_{d'|n}f(d')\sum_{d|\frac{n}{d'}}\mu(d)d∣n∑μ(d)d′∣dn∑f(d′)=d′∣n∑f(d′)d∣d′n∑μ(d)
再看上面的两条性质里的性质2,明白了吧QWQ!
∑d∣nμ(d)F(nd)=∑d′∣nf(d′)∑d∣nd′μ(d)=f(n)\sum_{d|n}\mu(d)F(\frac{n}{d})=\sum_{d'|n}f(d')\sum_{d|\frac{n}{d'}}\mu(d)=f(n)d∣n∑μ(d)F(dn)=d′∣n∑f(d′)d∣d′n∑μ(d)=f(n)
得证!
莫比乌斯反演的应用
例题:HDU1695
求对于区间[1,b]内的整数x和[1,d]内的y,满足gcd(x,y)=k的数对的个数。
只要让F(t)=满足gcd(x,y)%t==0的数对个数
f(t)=满足gcd(x,y)=t的数对个数,则F(t)和f(t)就存在莫比乌斯反演的关系了。显然F(t)=(b/t)*(d/t)
因为如果gcd(x,y)=1gcd(x,y)=1gcd(x,y)=1,则gcd(x∗k,y∗k)=kgcd(x*k,y*k)=kgcd(x∗k,y∗k)=k,所以我们把b和d同时除以k,得到的f(1)再去重就是答案。令lim=min(b/k,d/k),而根据上面的莫比乌斯反演第二个公式,
f(1)=∑dlimμ(d)∗F(d)f(1)=\sum_d^{lim}\mu(d)*F(d)f(1)=d∑limμ(d)∗F(d)
代码:
#include<iostream>
#include<cstdio>
#include<climits>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100005;
int T,a,b,c,d,e,tot;
long long ans1,ans2;
bool is[maxn];
int pri[maxn],miu[maxn];
void init(){//首先把莫比乌斯函数筛出来miu[1]=1;for(int i=2;i<=100000;i++){if(!is[i]){pri[++tot]=i;miu[i]=-1;}for(int j=1;j<=tot;j++){int k=pri[j]*i;if(k>100000)break;is[k]=1;if(i%pri[j]==0){miu[k]=0;break;}else miu[k]=-miu[i];}}
}
int main()
{int i,j,cnt=0;init();scanf("%d",&T);while(T--){cnt++;ans1=ans2=0;scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);if(!e){ printf("Case %d: 0\n",cnt);continue;}b/=e;d/=e;//如果gcd(x,y)=1,那么gcd(x*e,y*e)=e;if(b>d)swap(b,d);for(i=1;i<=b;i++)ans1+=(long long)miu[i]*(b/i)*(d/i);for(i=1;i<=b;i++)ans2+=(long long)miu[i]*(b/i)*(b/i);printf("Case %d: %lld\n",cnt,ans1-ans2/2);}return 0;
}
不过如果你遇上的是洛谷P3455什么的,那就还要用一个类似于分块的公共乘积优化啦,具体看下面的第4条,代码也贴着:
for(i=1;i<=a;i=j+1){j=min(a/(a/i),b/(b/i));ans+=(long long)(sum[j]-sum[i-1])*(a/i)*(b/i);//sum是miu的前缀和}
例题:bzoj2301/洛谷2522 problem b
这题和上题差不多吧…加上一个容斥就行了。容斥是这样的:
ans=find(b/k,d/k)-find((a-1)/k,d/k)-find((c-1)/k,b/k)+find((a-1)/k,(c-1)/k);
而find函数就是上文代码中的这一段:
for(i=1;i<=min(x,y);i=j+1){j=min(x/(x/i),y/(y/i));re+=(long long)(sum[j]-sum[i-1])*(x/i)*(y/i);}
例题:bzoj2820/洛谷P2257 YY的GCD
题目大意:给定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)为质数的(x, y)有多少对
假设n<mn<mn<m,此处/号代表向下取整
根据两题我们知道,通过f(n)=∑n∣dμ(dn)F(d)f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d)f(n)=∑n∣dμ(nd)F(d),然后设f(x)f(x)f(x)为gcd(a,b)=xgcd(a,b)=xgcd(a,b)=x的数对数,F(x)F(x)F(x)为x∣gcd(a,b)x|gcd(a,b)x∣gcd(a,b)的数对数,用莫比乌斯反演第二条可以求出式子:f(x)=∑x∣dμ(dx)nd∗mdf(x)=\sum_{x|d}\mu(\frac{d}{x})\frac{n}{d}*\frac{m}{d}f(x)=x∣d∑μ(xd)dn∗dm
再令上一个式子中的x=px=px=p,d=pid=pid=pi可得:
ans=∑isprime(p)n∑in(nip)(mip)μ(i)ans=\sum_{isprime(p)}^n \sum_i^n ( \frac{n}{ip})(\frac{m}{ip})\mu(i)ans=isprime(p)∑ni∑n(ipn)(ipm)μ(i)
意会一下就可以发现,假如设T=ipT=ipT=ip,那么就有:
ans=∑Tn(nT)(mT)∑p∣T且isprime(p)μ(Tp)ans=\sum_T^n ( \frac{n}{T})(\frac{m}{T}) \sum_{p|T且isprime(p)} \mu(\frac{T}{p})ans=T∑n(Tn)(Tm)p∣T且isprime(p)∑μ(pT)
这样我们预处理一下后面那团东西的前缀和即可,就这样。
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
#define ll long long
int read(){int q=0;char ch=' ';while(ch<'0'||ch>'9')ch=getchar();while(ch>='0'&&ch<='9')q=q*10+ch-'0',ch=getchar();return q;
}
const int maxn=10000005;
int n,m,T,tot,lim=10000000;
bool is[maxn];ll sum[maxn];
int pri[maxn>>1],mu[maxn];
void init(){int i,j,p;ll k;mu[1]=1;for(i=2;i<=lim;i++){if(!is[i]){pri[++tot]=i;mu[i]=-1;}for(j=1;j<=tot;j++){k=(ll)i*pri[j];if(k>lim)break;is[k]=1;if(i%pri[j])mu[k]=-mu[i];else break;}}for(i=1;i<=tot;i++)//预处理前缀和的办法for(j=1;pri[i]*j<=lim;j++)sum[pri[i]*j]+=mu[j];for(i=1;i<=lim;i++)sum[i]=sum[i-1]+sum[i];
}
int main()
{init();T=read();while(T--){n=read();m=read();if(n>m)swap(n,m);ll ans=0;for(int i=1,j;i<=n;i=j+1){j=min(n/(n/i),m/(m/i));//一毛一样的优化ans+=(ll)(n/i)*(ll)(m/i)*(ll)(sum[j]-sum[i-1]);}printf("%lld\n",ans);}return 0;
}
例题:bzoj2005/洛谷1447 能量采集
dalao们的题解经常长这样:水题,贴代码
水吗…蒟蒻泪流满面。
好吧好吧,那蒟蒻就来跟着dalao推一推。
1.容易意会得到,一颗坐标为(x,y)植物连线上的植物数量就是gcd(x,y)-1;
题目中的式子变一下,主要矛盾是求∑x=1n∑y=1mgcd(x,y)\sum_{x=1}^n \sum_{y=1}^m gcd(x,y) x=1∑ny=1∑mgcd(x,y)
2.首先有一条结论:一个数的所有因子的欧拉函数之和等于这个数本身。
然后x和y的公因子肯定是他们最大公约数的因子,所以就是求∑x=1n∑y=1m∑d=1n[d∣n且d∣m]ϕ(d)\sum_{x=1}^n \sum_{y=1}^m \sum_{d=1}^n[d|n且d|m] \phi(d)x=1∑ny=1∑md=1∑n[d∣n且d∣m]ϕ(d)
3.随便交换律一下得到:∑d=1n∑i=1n[d∣n]∑j=1m[d∣m]ϕ(d)∗(n/i)∗(m/i)\sum_{d=1}^n \sum_{i=1}^n[d|n] \sum_{j=1}^m[d|m]\phi(d)*(n/i)*(m/i)d=1∑ni=1∑n[d∣n]j=1∑m[d∣m]ϕ(d)∗(n/i)∗(m/i)
注意:n/i和m/i是向下取整,下同
4.现在求起来就方便多了,不过呢,还有一个优化,对于一个数i来说,设它的n/i=k1,m/i=k2n/i=k_1,m/i=k_2n/i=k1,m/i=k2,则同样满足n/j=k1,m/j=k2n/j=k_1,m/j=k_2n/j=k1,m/j=k2的最大j=min(n/k1,m/k2);j=min(n/k_1,m/k_2);j=min(n/k1,m/k2);
5.最后把得到的结果乘以2再减去m*n即可
#include<iostream>
#include<cstdio>
#include<climits>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
ll n,m,ans;int tot;
bool is[1000010];
int pri[1000010],phi[10000100];
ll sum[1000010];
void init(){ll i,j,k;phi[1]=1;for(i=2;i<=n;i++){if(!is[i]){phi[i]=i-1;pri[++tot]=i;}for(j=1;j<=tot;j++){k=pri[j]*i;if(k>n)break;is[k]=1;if(i%pri[j]==0){phi[k]=(ll)phi[i]*pri[j];break;}else phi[k]=(ll)(pri[j]-1)*phi[i];}}for(i=1;i<=n;i++)sum[i]=sum[i-1]+phi[i];
}
int main()
{ll i,j;scanf("%lld%lld",&n,&m);if(n>m)swap(n,m);init();for(i=1;i<=n;i=j+1){j=min(m/(m/i),n/(n/i));ans+=(ll)(sum[j]-sum[i-1])*(m/i)*(n/i);}ans=(ll)ans*2-(ll)n*m;printf("%lld",ans);return 0;
}
其他练习
相信你经过例题的磨炼,已经对莫比乌斯反演的应用有了基本的了解,下面我们再来几道水题练练手吧。
bzoj2154/bzoj2693/洛谷P1829 Crash的数字表格:题解戳我QvQ
bzoj3994/洛谷P3327 约数个数和:题解戳我QvQ
bzoj3529/洛谷P3312 数表:题解戳我QvQ
洛谷P3768 简单的数学题:题解戳我QvQ
bzoj4816/洛谷P3704/loj2000 数字表格:虽然利用莫比乌斯反演的方法很常规,但是这种相乘的变化还是挺新鲜的。
初涉莫比乌斯反演(附带例题)相关推荐
- 初探莫比乌斯反演及欧拉反演
莫比乌斯反演是数论中非常重要的一部分,它可以将一个本来只能用时间复杂度极高的枚举求和过程,通过反演变成一个线性时间复杂度甚至根号级别的时间复杂度的问题.在这里,总结一下本人在学习莫比乌斯反演(附带一部 ...
- python莫比乌斯内接矩形_莫比乌斯反演例题集 ^_^(示例代码)
[luogu 2257]YY的GCD 预备知识 除法分块.莫比乌斯反演 最终公式: (ans= sum_{T=1}^n (frac{n}{T}) (frac{m}{T}) sum_{p|t,ispri ...
- 模板 - 莫比乌斯反演(常用技巧)
整理的算法模板合集: ACM模板 目录 莫比乌斯反演 常用技巧 经典模板例题 莫比乌斯反演 莫比乌斯函数: μ(n)={0∃i∈[1,m],Ci>1(−1)m∀i∈[1,m],Ci=1\mu(n ...
- 【算法笔记】莫比乌斯反演(包含定理,两种形式的证明及入门经典模板)
整理的算法模板合集: ACM模板 目录 一.莫比乌斯反演 二.几个概念和定理 三.两种形式的莫比乌斯反演证明 四.POJ 3904 Sky Code(入门例题) 一.莫比乌斯反演 学习笔记,我是看这个 ...
- 莫比乌斯函数+莫比乌斯反演
几个经典的莫比乌斯反演练习题 先来一个莫比乌斯函数板子 1 int N = 10000000; 2 int not_prim[10000050],prim[10000050]; 3 long long ...
- 【莫比乌斯反演】10.30破译密码
初涉的话先留坑吧 题目大意 $\sum_{i_1}^{a_1}\sum_{i_2}^{a_2}\cdots\sum_{i_m}^{a_m}(i_1,i_2,\cdots,i_m)$ $a_i<= ...
- 数论 —— 莫比乌斯反演
[反演] 假设我们手头有个数列 F,通过某种变换 H,可以得到函数 G.,即: 但现在只有函数 G,需要求 F,那么我们就需要寻找一种变换 ,使得 G 在经过这种变换后能够获得 F,这个过程即为反演, ...
- 莫比乌斯反演学习笔记
背景: 之前不会用MarkdownMarkdownMarkdown,所以坑没有补. 定义: 以下除法默认向下去整. 对于一个形如Fn=∑d∣nfdF_n=\sum_{d|n}f_dFn=∑d∣nf ...
- 莫比乌斯反演小结 + 黑暗爆炸 2301
1.前言 莫比乌斯反演课上听蒙了,后来重新捋了一遍思路,看了一下示例,就明白了,写篇学习笔记总结下 2.一些引理 引理1 (莫比乌斯定理) ∑d∣nμ(n)={1,n=10,n≠1\sum_{d|n} ...
最新文章
- python 搜索旋转排序数组
- 一款炫酷Loading动画--载入成功
- win10无法开启夜间模式
- webpack 的webpack.config文件配置css-loader,style-loader注意的问题
- net4.0的从客户端中检测到有潜伏危险的 Request.Form
- Visio图标模板库
- html单元格下拉菜单怎么做,Excel 2013如何制作下拉菜单?(excel下拉菜单怎么做?)...
- LOE是什么?如何加入?
- PPP协议身份验证PAP和CHAP
- 亚马逊多账号防关联技巧
- 干支纪年法简便算法_2020年天干地支对照表,干支日历表
- 酷狗音乐微信小程序插件使用实践
- jitter单位_抖动(jitter)测量
- bootmgr快速修复win7_win7 iso镜像下载(Win7安装版_非GHOST ISO镜像)
- Friends经典对白
- 怎么录制屏幕视频?电脑按哪个键录制屏幕
- Creo 9.0在草图环境中创建坐标系
- 不同型号的二极管模块并联_常见消防模块的接线方法和实物演示
- 串口升级华为S2300系列交换机
- 滴滴如何调度_滴滴研究院:解读滴滴调度系统中的人工智能
热门文章
- 华为实验24-vRRP基本配置
- C语言大数运算-乘除法篇
- 全网独家解决方案: doccano报错 Your models in app(s): ‘api‘ have changes that are not yet reflected in a migrat
- 【Vue】如何请求后台数据
- 消息Hander dispatchfalled; nested excepton is java.ang.NOSuchMethodError: org.springramewrk.utl.tring
- Ubuntu下Madagascar安装教程
- 第一个hollo world程序
- 第二十讲 DES算法简介
- python内置函数getattr()和setattr()
- 李彦宏派出自家司机,央视主持人彻底被惊到了:人呢?人呢?