莫比乌斯(Mobius)反演知识整合
前言
虽然我去年就已经学过这东西了,但是一直没有整理、归纳。而且我发现我对它的套路不够熟悉、对它的理解不够透彻,卒致GDOIDay2T1没切(详细事故记录戳这里)。所以,在此做一个知识整合。
引子
先来看bzoj的一道题:Problem b。
Problem
给出n组询问,每组询问给出a、b、c、d、k五个整数,求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k。
Hint
100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000
Solution
首先,考虑转化一下。既然Ans=∑bx=a∑dy=cδ(x,y)kAns=∑x=ab∑y=cdδ(x,y)kAns=\sum_{x=a}^b \sum_{y=c}^d \delta_{(x,y)k}(δδ\delta为克罗内克函数),那么其实我们可以给a、b、c、d同除以一个k,转化为求δ(x,y),1δ(x,y),1\delta_{(x,y),1}。
考虑设Ans(n,m)=∑⌊nk⌋x=1∑⌊mk⌋y=1δ(x,y)1Ans(n,m)=∑x=1⌊nk⌋∑y=1⌊mk⌋δ(x,y)1Ans(n,m)=\sum_{x=1}^{\lfloor\frac nk\rfloor} \sum_{y=1}^{\lfloor\frac mk\rfloor} \delta_{(x,y)1},则原问题的答案=Ans(b,d)−Ans(a−1,d)−Ans(b,c−1)+Ans(a−1,c−1)Ans(b,d)−Ans(a−1,d)−Ans(b,c−1)+Ans(a−1,c−1)Ans(b,d)-Ans(a-1,d)-Ans(b,c-1)+Ans(a-1,c-1)。
于是原问题转化为求解Ans(n,m)Ans(n,m)Ans(n,m)。
对于每个询问,都可以用O(⌊bk⌋∗⌊dk⌋)O(⌊bk⌋∗⌊dk⌋)O(\lfloor \frac bk \rfloor * \lfloor \frac dk \rfloor)的时间复杂度求出Ans数组,然后计算Ans。
然而,这依然不尽人意。
考虑设f(k)=∑nx=1∑my=1δ(x,y)kf(k)=∑x=1n∑y=1mδ(x,y)kf(k)=\sum_{x=1}^n \sum_{y=1}^m \delta_{(x,y)k},先保证n<m,否则交换。
直接计算f(k)很难。
那么,再设g(k)=∑nx=1∑my=1[k|(x,y)]g(k)=∑x=1n∑y=1m[k|(x,y)]g(k)=\sum_{x=1}^n \sum_{y=1}^m [k|(x,y)],即满足k为(x,y)的约数的数对(x,y)的个数,则g(k)=∑⌊nk⌋d=1f(k∗d)g(k)=∑d=1⌊nk⌋f(k∗d)g(k)=\sum_{d=1}^{\lfloor \frac nk \rfloor} f(k*d)。
g(k)的求解很容易,符合x=k∗x1(1≤x1≤⌊nk⌋),y=k∗y1(1≤y1≤⌊mk⌋)x=k∗x1(1≤x1≤⌊nk⌋),y=k∗y1(1≤y1≤⌊mk⌋)x=k*x1(1≤x1≤\lfloor \frac nk \rfloor),y=k*y1(1≤y1≤\lfloor \frac mk \rfloor)的数对(x,y)的个数即为答案。所以g(k)=⌊nk⌋∗⌊mk⌋g(k)=⌊nk⌋∗⌊mk⌋g(k)=\lfloor \frac nk \rfloor*\lfloor \frac mk \rfloor。
然而,我们虽然貌似知道了很多,实际上并没有什么卵用。还有一个至关重要的难题亟待解决:如何用g(k)求解f(k)呢?
这时,莫比乌斯反演闪亮登场!
反演
反演到底是什么?
我觉得这篇博客讲得十分详尽。大意如下:
对于一个数列{f}来说,如果我们知道另外一个数列{g},满足如下条件:
g_n=\sum_{i=0}^n a_i*f_i
反演(inversion)就是利用{g}来表示出{f}:
f_n=\sum_{i=0}^n b_i*g_i
也就是说,反演的原理就是容斥。
下面的“莫比乌斯反演的引入”实质上就是反演。当然,如果你做的莫比乌斯反演的题多了,你会发觉,不仅是它,所有的莫比乌斯反演题的解法实质上都是反演。
莫比乌斯反演的引入
由于这段东西过于重要,所以不得不写一下。
但是,由于这段东西又过于冗长,所以我在网上截了两张图。
声明:以下两张图片截图自百度百科。
莫比乌斯函数
定义μ(n)μ(n)\mu(n)为自变量为n(n∈N∗n∈N∗n \in N*)时的莫比乌斯函数。若设n=x1a1∗x2a2∗x3a3∗⋅⋅⋅∗xpapn=x1a1∗x2a2∗x3a3∗···∗xpapn=x1^{a1}*x2^{a2}*x3^{a3}*···*xp^{ap},其中∀xi∀xi\forall xi为n的质因子,则μμ\mu的取值如下:
\mu(n)=\left\{ \begin{aligned} 1 & & n=1 \\ 0 & & ai \in a \land ai>1\\ (-1)^p & & \forall ai=1 \end{aligned} \right.
也就是说,当n=1时,μ(n)=1μ(n)=1\mu(n)=1;当n有重复质因子时,μ(n)=0μ(n)=0\mu(n)=0;当n无重复质因子时,μ(n)=(−1)pμ(n)=(−1)p\mu(n)=(-1)^p。
因此,μμ\mu为积性函数,可通过线筛顺带O(n)O(n)O(n)求出。
那么,如何用这个函数求解上面那题呢?
性质1:
\sum_{d|n} \mu(d)=\left\{ \begin{aligned} 1 & & n=1 \\ 0 & & n>1 \end{aligned} \right.
这个怎么证明呢?
依然设n=x1a1∗x2a2∗x3a3∗⋅⋅⋅∗xpapn=x1a1∗x2a2∗x3a3∗···∗xpapn=x1^{a1}*x2^{a2}*x3^{a3}*···*xp^{ap},再设d=x1b1∗x2b2∗x3b3∗⋅⋅⋅∗xpbpd=x1b1∗x2b2∗x3b3∗···∗xpbpd=x1^{b1}*x2^{b2}*x3^{b3}*···*xp^{bp}。显然,若要μ(d)μ(d)\mu(d)≠0,则须满足∀bi≤1∀bi≤1\forall bi≤1。设有q个bi为1,其余均为0,则可推出:
\sum_{d|n}=\binom pq (-1)^q
这和组合数扯上关系了。可以观察杨辉三角推出性质1,当然,我们也可以更严谨地,通过(被苹果砸死的)牛顿提出的二项式定理推出性质1。
性质2:μ(n)μ(n)\mu(n)是积性函数。
这个,看一看积性函数的定义,很显然,就不解释了。
莫比乌斯反演的证明
下面的内容也比较重要,但是非常冗长,故贴上两张图片instead of手打:
回到引子
重温一下,我们已知下式:
g(k)=\sum_{d=1}^{\lfloor \frac nk \rfloor} f(k*d)
现在我们要通过g(k)求出f(k)。
通过莫比乌斯反演的变形可知:
f(k)=\sum_{d=1}^{\lfloor \frac nk \rfloor} g(k*d)*\mu(d)=\sum_{d=1}^{\lfloor \frac nk \rfloor} \lfloor \frac n{k*d} \rfloor*\lfloor \frac m{k*d} \rfloor*\mu(d)
设T=k*d,则上式可以变得简洁些:
f(k)=\sum_{d=1}^{\lfloor \frac nk \rfloor} \lfloor \frac nT \rfloor*\lfloor \frac mT \rfloor*\mu(d)
于是,对于每个询问,我们可以用O(min(⌊nk⌋,⌊mk⌋))O(min(⌊nk⌋,⌊mk⌋))O(min(\lfloor\frac nk\rfloor,\lfloor\frac mk\rfloor))的时间复杂度求出f。
但还是过不了。
这时,我们考虑祭上莫比乌斯反演的又一强力套路:
分块
首先,我们知道,⌊nT⌋⌊nT⌋\lfloor\frac nT\rfloor这东西是只有1∼n−−√1∼n1 \sim \sqrt n这n−−√n\sqrt n种取值的;同理,⌊mT⌋⌊mT⌋\lfloor\frac mT\rfloor也只有m−−√m\sqrt m种取值。
想象在一条直线上,⌊nT⌋⌊nT⌋\lfloor\frac nT\rfloor和⌊mT⌋⌊mT⌋\lfloor\frac mT\rfloor的每一种取值都映射成该条直线上的一点,那么至多会有n−−√+m−−√n+m\sqrt n + \sqrt m个点。以最左最右两点取闭区间,则这个闭区间可视作一条线段,且此线段被它身上的n−−√+m−−√n+m\sqrt n + \sqrt m个点分成n−−√+m−−√−1n+m−1\sqrt n + \sqrt m -1条子线段。
这些子区间内的⌊nT⌋⌊nT⌋\lfloor\frac nT\rfloor和⌊mT⌋⌊mT⌋\lfloor\frac mT\rfloor的取值都是分别相同的,所以可以考虑一起计算。
那么,考虑预处理出μμ\mu的前缀和,然后对于每种不同的⌊nT⌋⌊nT⌋\lfloor\frac nT\rfloor和⌊mT⌋⌊mT⌋\lfloor\frac mT\rfloor段分别计算一下即可。
于是,计算f的时间复杂度就被缩减为O(n−−√+m−−√)O(n+m)O(\sqrt n + \sqrt m)。
例题
当然,除过bzoj的Problem b,还是有不少简单的莫比乌斯反演题滴。
bzoj上的DZY loves Math(也即jzoj上的Wyx)、bzoj上的于神之怒加强版(也即jzoj上的于神之怒)都是比较经典的莫比乌斯反演,套路大致相同。
山东省选2015第一轮第一试的约数个数和(英文divisor,jzoj上也有)则是一道比较有思维难度的题,还要转换一下式子。
特点
- 题目大意都比较简洁明了
- 要求的答案都和gcd脱不了干系
- 画风比较诡异
- 要推很多很多、很长很长的式子,因而会蚕食你一页多的草稿纸
- 一般出现在省选Day2T1
要点
- 第零步:牢记莫比乌斯反演的几种变化形式
- 第一步:将含有gcd的项移到后面,利用莫比乌斯函数的性质1将其转化成∑d|kμ(d)∑d|kμ(d)\sum_{d|k} \mu(d)
- 第二步:将含有μμ\mu的项移到前面,突破僵局,利用等差数列等公式拆掉后面的几个∑∑\sum
- 第三步:看到式子被化简成一重循环的时候,就可以上分块了
压轴大戏——谈笑风生
不要以为我要谈笑风生,我说的是GDOIDay2T1。
Problem
给定一个N个点、M条边的图,点i的点权为a[i]。对于边u→vu→vu \to v,其边权len=∑a[u]i=1∑a[v]j=1δ(i,j)1∗(i+j)len=∑i=1a[u]∑j=1a[v]δ(i,j)1∗(i+j)len=\sum_{i=1}^{a[u]} \sum_{j=1}^{a[v]} \delta_{(i,j)1}*(i+j),即经过这条边要花len秒。小熊维尼一开始在点1,他想在T秒内走到点n,而他能花P点能量使所有边的边权减少P且不能减至0。求最少需要花费多少能量才能在T秒内到达,以及在此前提下,最少要花费多少秒。
Hint
Solution
比赛时我看了一会,发现这道题是两道题拼起来的题:求解边权+二分spfa。
那么,二分spfa谁都会打,关键就在于求解边权了。
However,在比赛时我并没有想到正解,甚至连莫比乌斯反演也没有想多久。
下面现场推一波式子:
len=\sum_{i=1}^{a[u]} \sum_{j=1}^{a[v]} \delta_{(i,j)1}*(i+j)
设a[u]<a[v],不满足则交换。
根据莫比乌斯函数的性质1,可将δ(i,j)1δ(i,j)1\delta_{(i,j)1}这个东西改换一下:
len=\sum_{i=1}^{a[u]} \sum_{j=1}^{a[v]} (i+j) * \sum_{x|(i,j)} \mu(x)
考虑将后面的∑x|(i,j)μ(x)∑x|(i,j)μ(x)\sum_{x|(i,j)} \mu(x)挪到前面,然后用i、j枚举x的倍数:
len=\sum_{x=1}^{a[u]} \mu(x)*\sum_{i=1}^{\lfloor \frac{a[u]}x \rfloor} \sum_{j=1}^{\lfloor \frac{a[v]}x \rfloor} x*(i+j)
瞄到后面有一个x,果断将其挪到前面:
len=\sum_{x=1}^{a[u]} \mu(x)*x*\sum_{i=1}^{\lfloor \frac{a[u]}x \rfloor} \sum_{j=1}^{\lfloor \frac{a[v]}x \rfloor} (i+j)
考虑将后面的i、j分开处理,分别计算它们出现的次数,于是可以推出下式:
len=\sum_{x=1}^{a[u]} \mu(x)*x* [ ( \sum_{i=1}^{\lfloor \frac{a[u]}x \rfloor} i * \lfloor \frac{a[v]}x \rfloor ) + ( \sum_{j=1}^{\lfloor \frac{a[v]}x \rfloor} j * \lfloor \frac{a[u]}x \rfloor) ]
运用等差数列求和公式可以拆掉后面的两个∑∑\sum:
len=\sum_{x=1}^{a[u]} \mu(x)*x* ( \frac{\lfloor \frac{a[u]}x \rfloor * (1+\lfloor \frac{a[u]}x \rfloor)}2 * \lfloor \frac{a[v]}x \rfloor + \frac{\lfloor \frac{a[v]}x \rfloor * (1+\lfloor \frac{a[v]}x \rfloor)}2 * \lfloor \frac{a[u]}x \rfloor)
我们发现后面要相加的冗长式子有公因式,于是合并同类项:
len=\sum_{x=1}^{a[u]} \mu(x)*x* \frac{ \lfloor \frac{a[u]}x \rfloor * \lfloor \frac{a[v]}x \rfloor * ( 2 + \lfloor \frac{a[u]}x \rfloor + \lfloor \frac{a[v]}x \rfloor ) }2
前面的μ(x)∗xμ(x)∗x\mu(x)*x可以预处理前缀和。
后面的式子,我们发现它的取值只与⌊a[u]x⌋⌊a[u]x⌋\lfloor \frac{a[u]}x \rfloor和⌊a[v]x⌋⌊a[v]x⌋\lfloor \frac{a[v]}x \rfloor有关,而它们至多只有a[u]−−−√+a[v]−−−√a[u]+a[v]\sqrt{a[u]}+\sqrt{a[v]}种不同取值,于是可以分块处理。
时间复杂度:线筛求μ(x)O(max{ai})μ(x)O(max{ai})\mu(x)O(max\{ai\}),预处理前缀和O(max{ai})O(max{ai})O(max\{ai\}),计算每条边边权O(∑Mi=1a[ui]−−−−√+a[vi]−−−−√)O(∑i=1Ma[ui]+a[vi])O(\sum_{i=1}^M \sqrt{a[u_i]} + \sqrt{a[v_i]}),二分最短路O(log2max{len}∗最短路复杂度)O(log2max{len}∗最短路复杂度)O(log_2max\{len\} * 最短路复杂度)。
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
#define ll long long
#define fo(i,a,b) for(i=a;i<=b;i++)
const int N=1e4+1,M=N<<2,A=1e5;
int i,j,mu[A+1],cnt,prime[A+1],x;
bool p[A+1];
ll sum[A+1];
void init()
{memset(p,1,sizeof p);mu[1]=sum[1]=1;fo(i,2,A){if(p[i]){prime[++cnt]=i;mu[i]=-1;}for(j=1;j<=cnt&&(j==1||i%x)&&i*(x=prime[j])<=A;j++){p[i*x]=0;mu[i*x]=i%x?-mu[i]:0;}sum[i]=sum[i-1]+(ll)mu[i]*i;}
}int n,m,a[N],u,v;
ll T,Len;
void Mobius(ll n,ll m)
{if(n>m)swap(n,m);ll i=1,j,ni,mi;Len=0;while(i<=n){j=min(n/(ni=n/i),m/(mi=m/i));Len+=(sum[j]-sum[i-1])*ni*mi*(2+ni+mi)>>1;i=j+1;}
}
int tot,tov[M],next[M],last[N];
ll len[M],maxP;
inline void link(int x,int y)
{tov[++tot]=y;len[tot]=Len;next[tot]=last[x];last[x]=tot;
}
void scan()
{scanf("%d%d%lld",&n,&m,&T);fo(i,1,n)scanf("%d",&a[i]);if(n==1){printf("0 0");exit(0);}fo(i,1,m){scanf("%d%d",&u,&v);Mobius(a[u],a[v]);maxP=max(maxP,Len);link(u,v);link(v,u);}
}int y,head,tail,que[A*10];
ll dis[N];
bool exist[N];
inline ll calc(ll P){return max(len[i]-P,0ll);}
ll spfa(ll P)
{memset(dis,127,sizeof dis);head=dis[que[tail=1]=1]=0;memset(exist,0,sizeof exist);exist[1]=1;while(head<tail){x=que[++head];for(i=last[x];i;i=next[i])if(dis[y=tov[i]]>dis[x]+calc(P)){dis[y]=dis[x]+calc(P);if(!exist[y]){exist[que[++tail]=y]=1;if(dis[que[head+1]]>dis[y])swap(que[head+1],que[tail]);}}exist[x]=0;}return dis[n];
}
void Bsort()
{ll l=0,r=maxP,mid;while(l<r){mid=l+r>>1;if(spfa(mid)<=T)r=mid;else l=mid+1;}printf("%lld %lld",l,spfa(l));
}int main()
{freopen("magic.in","r",stdin);freopen("magic.out","w",stdout);init();scan();Bsort();
}
莫比乌斯(Mobius)反演知识整合相关推荐
- Mobius反演和筛法
Mobius反演和筛法 前置知识:积性函数.Dirichlet卷积.莫比乌斯函数.数论分块 积性函数 定义: 1.若f(n)的定义域为正整数域,值域为复数,即f: Z^+ →C,则f(n)为数论函数: ...
- SPOJ PGCD (mobius反演 + 分块)
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove 题意 :求满足gcd(i , j)是素数(1 &l ...
- Mobius反演学习
这篇文章参考了许多资料和自己的理解. 先放理论基础. 最大公约数:小学学过,这里只提一些重要的公式: $·$若$a=b$,则$\gcd(a,b)=a=b$: $·$若$\gcd(a,b)=d$,则$\ ...
- 关于Mobius反演
欧拉函数 \(\varphi\) \(\varphi(n)=\)表示不超过 \(n\) 且与 \(n\) 互质的正整数的个数 \[\varphi(n)=n\cdot \prod_{i=1}^{s}(1 ...
- 无需多个模型也能实现知识整合?港中文MMLab提出「烘焙」算法,全面提升ImageNet性能...
视学算法专栏 转载自:机器之心 作者:葛艺潇 来自港中文 MMLab 的研究者提出一种烘焙(BAKE)算法,为知识蒸馏中的知识整合提供了一个全新的思路,打破了固有的多模型整合的样式,创新地提出并尝试了 ...
- “烘焙”ImageNet:自蒸馏下的知识整合
©作者|葛艺潇 学校|香港中文大学博士生 研究方向|图像检索.图像生成等 最先进的知识蒸馏算法发现整合多个模型可以生成更准确的训练监督,但需要以额外的模型参数及明显增加的计算成本为代价.为此,我们提出 ...
- Github项目推荐 | OI Wiki:编程竞赛最全知识整合站点
编程竞赛发展多年,难度越来越高,内容越来越复杂,而网上资料大多零散,初学者往往并不知道如何系统地学习相关知识,需要花费大量时间摸索. OI (Olympiad in Informatics,信息学奥林 ...
- coderwhy--前端知识整合包--htmlcss05
coderwhy–前端知识整合包–html/css05 一.css属性-display 块级元素由来:display:block(所有浏览器默认添加,块级元素本就是行内级元素是因为浏览器默认添加上面那 ...
- 莫比乌斯(mobius)笔记
mobius反演的本质是容斥原理,这在<组合数学>里面有提到 基本公式定理 mobius反演公式 F(n)f(n)=∑d∣nf(d)=∑d∣nμ(n/d)F(d)=∑d∣nμ(d)F(n/ ...
最新文章
- 谷歌砸出10亿美元,要为湾区困难群众,建2万套经适房
- 【Java 虚拟机原理】Java 引用类型 ( 强引用 | 软引用 | 弱引用 | 虚引用 | 静态变量 )
- 叹西安2014中秋节雨天
- 7月份计划-----dream
- HDFS【2.5.1】系列1:HDFS的核心数据结构---元数据
- extjs Accordion 怎样把展开符号:加号(+)放在左边?
- Express--socket.io使用session验证
- Redis能干啥?细看11种Web应用场景
- android hook底层代码_Java-Hook技术-入门实践(反射、动态代理)-Hook拦截通知(当前App/Context)...
- 查找字符串中元素出现的次数
- python好用的模块_Python中好用的模块们
- c语言除法计算和取模计算
- 使用iso镜像文件创建yum源
- 软考(14)-接入网技术-sonet/sdh
- python-直接删除整个文件夹
- 解决跨域(六)--- document.domian
- vscode背景图片无法删除
- 区分定理(Theorem)、引理(Lemma)、推论(Corollary)等概念
- Feature Selection详解(附带Relief、Relief-F、LVM详解)(一)
- 专访容智信息柴亚团:终极愿景是助力天下企业成为数字化孪生组织