Mobius反演总结

刷了一些浅显的反演题目, 做一个总结

知识点1

给定n个数(可以是1-n), 求有多少数与x互质

f(x)=d|xu[d]cnt[d]

其中 u[d] 是mobius函数 cnt[d] 表示原n个数中有多少个d的倍数
这更像一个容斥原理的知识点

1.1:CodeForces 547C

直接套一下知识点1的公式就可以了。

1.2:阿里云秘钥池

链接:https://nanti.jisuanke.com/t/15966
本题看上去是数位dp, 但是1e5的状态乘1e5的转移时间复杂度太高。
知识点1的公式略作变通,复杂度为 O(p  )
代码: http://paste.ubuntu.com/25018690/

1.3: 求与x公约数为k的数的数量

f(x,k)=d|xku[d]cnt[dk]

1.4: CodeForces 585E

https://vjudge.net/contest/151569#problem/H
题意: 给n个数,从中找出一个数 x 和一个非空的集合S, 要求 gcd(S) !=1 gcd(S,x)==1 求这样的组合有多少。

关键:若 x 在集合S中, 且 gcd(x,S)==1 gcd(S)==1
有这个关键点后,这题做法就很多了
做法1(题解做法):对于全部n个数,求出gcd为1的集合数量A(知识点2),再用 2n1 减去这个A,得到gcd不为1的集合的数量B。对于每一个数x,减去B中不与x互质的集合的数量,再求和就是结果(计算时 cnt[d] 是要算上x的)。
做法2(我认为理论可行):对于全部n个数,求出gcd为1的集合数量A(知识点2)。对于每一个数x, 在计算A时其共影响了(x的约数)项, 这样我们可以求出剩下n-1个数中,与x最大公约数结果为1的集合数量A’。可以用知识点1求出n-1个数中与x互质的集合的数量B,计算B-A’,再求和即可。
http://paste.ubuntu.com/25023231/

知识点2

F(d)=d|nf(n)f(d)=d|nu[nd]F[n]

这个公式要看仔细了
《挑战程序设计竞赛》我映像里是没有给出这个式子的,但是事实上我一个专题做下来,mobius考的主要就是这个公式
最基础的题目: HDU 1695 http://acm.hdu.edu.cn/showproblem.php?pid=1695
令F[i]表示 从(1,1) 到 (n,n)中有多少对数的gcd是i的倍数
令f[i]表示 从(1,1) 到 (n,n)中有多少对数的gcd恰好是i
再套一下上面的式子

2.1: SPOJ - VLATTICE

从二维拓展到三维,很简单

2.2: HackerRank - gcd-product

https://www.hackerrank.com/contests/w3/challenges/gcd-product
例题扩展到了所有素数,但是幸运的是数据单组, 理论上O(nlogn)可以跑过,大常数选手表示叹息。
假设 n=m=1.5e7 那么 F[1e7]=F[1.1e7]=...=1 这样我们可以将F[i]相同的分成同一块,然后mobius处理一下前缀和,总体而言除法做的少了,优化了一下常数。
代码: http://paste.ubuntu.com/25018880/

2.3: SPOJ - PGCD

http://www.spoj.com/problems/PGCD/en/
2.2的加强版,多组数据,时限还非常短
假设 nm , 别人发现了, 只有当 ni F[i] 才会被用到,而且用到多少次是与 n,m 无关的, 预处理用到时的u[d] 的和
再加上2.2的分块,据说单组复杂度可以降到 O(sqrtn)

2.4:UVA - 12631

https://vjudge.net/contest/151569#problem/I
题意: 某世界有n种货币, 货币价值分别为price[i], n种货币共有 2n1 种可能的组合。
现在假设某样商品价值为A, 对于每一种货币组合,要求出当顾客和商家都持有无限量组合内货币时,通过付钱与找零是否能完成交易。 假设商品价值为A时,共有 F[A] 种, 输出 (Ci=1F[i])mod1e9+7
本题还有第二问,限定货币组合内货币种类为k种, 再输出一个结果

由扩展欧几里得定理可知:设货币集合为S,只有当 gcd(S)|A 时交易可以完成
这样就转化为知识点2下的一个普通问题了,只是本题同时还运用了组合数的知识,所以稍微提一下。
代码:http://paste.ubuntu.com/25019109/

知识点3

n=d|nφ(d)

其实这个知识点感觉不算反演的

3.1: Cowslip Collections

题意:已有n个数, 还要插入m个数,对于第i次插入,求出前(n+i)个数所有大小为K的子集的gcd和
做法:每次插入一个x, 会影响到gcd为x的约数的集合的数量,如果要分别更新出每一种集合的数量,需要 O(m2) , TLE了
但由于我们很容易算出有多少个集合的gcd是d的倍数 F[d] ,所以我们可以计算

i=1100,000F[i]φ[i]

而每次插入一个x,我们影响到的F[i],只有x的约数项,复杂度 O(m)
http://paste.ubuntu.com/25023319/

部分题目

HDU 6134 Battlestation Operational

题意:求

f(n)=i=1nj=1iij[(i,j)=1]

做法
为了方便起见,引入两个二参数的函数
G(n,x)=i=1nj=1iij[x|(i,j)]g(n,x)=i=1nj=1iij[(i,j)=x]

可以发现 g(n,1)=f(n)  G(n,x)=G(nx,1)
函数 G 和函数g 就满足了 mobius  递推中的 G(n,x)=x|dg(n,d)
所以要求的 g(n,1)=nd=1u[d]G(n,d)
反思
赛场上CC是给出了到这里的式子的,但是我这里的函数名g(n,x)他是用f(x)给出的,一来和题目给的函数名重了,二来我比赛的时候脑子也很混,难以分清楚n在函数中的地位到底是一个参数还是一个定量。故遇到mobius的题目,为了帮助自己尽快理清思路,我认为应该设一个多元函数出来。

题意:求

S(A,B)=a=1Ab=1Babf(gcd(a,b))f(x)={x0x is a square free numberelse

做法
对于每一个是 square free 的x 算出有哪些ab对的最大公因数是x
F(A,B,x)=a=1Ab=1Bab [x|(a,b)]f(A,B,x)=a=1Ab=1Bab [(a,b)=x]

这两个式子很显然 mobius f(A,B,x) 最后
ans=x=1xf(A,B,x) [u(x)!=0]

再对以上过程做一些贡献优化之类的
反思
1. 这道题因为发现有 gcd(a,b) , 然后之前做了一些 gcd 值的求和问题,都是用 phi 函数做的。一开始就不停地试图往这个上面去想,但是欧拉函数似乎只适用于不管 gcd(a,b) 是多少都要统计进去的题目。
2. AC后十天就完全无法想起这道题的思路,没有主动想过从枚举 gcd 值计算来下手,之后要牢牢记住这个思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值