刷了一些浅显的反演题目, 做一个总结
知识点1
给定n个数(可以是1-n), 求有多少数与x互质
其中 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的数的数量
1.4: CodeForces 585E
https://vjudge.net/contest/151569#problem/H
题意: 给n个数,从中找出一个数
x
和一个非空的集合
关键:若
x
在集合
有这个关键点后,这题做法就很多了
做法1(题解做法):对于全部n个数,求出gcd为1的集合数量A(知识点2),再用
2n−1
减去这个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
这个公式要看仔细了
《挑战程序设计竞赛》我映像里是没有给出这个式子的,但是事实上我一个专题做下来,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的加强版,多组数据,时限还非常短
假设
n≤m
, 别人发现了, 只有当
n≥i
时
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种货币共有
2n−1
种可能的组合。
现在假设某样商品价值为A, 对于每一种货币组合,要求出当顾客和商家都持有无限量组合内货币时,通过付钱与找零是否能完成交易。 假设商品价值为A时,共有
F[A]
种, 输出
(∑Ci=1F[i])mod1e9+7
本题还有第二问,限定货币组合内货币种类为k种, 再输出一个结果
由扩展欧几里得定理可知:设货币集合为S,只有当
gcd(S)|A
时交易可以完成
这样就转化为知识点2下的一个普通问题了,只是本题同时还运用了组合数的知识,所以稍微提一下。
代码:http://paste.ubuntu.com/25019109/
知识点3
其实这个知识点感觉不算反演的
3.1: Cowslip Collections
题意:已有n个数, 还要插入m个数,对于第i次插入,求出前(n+i)个数所有大小为K的子集的gcd和
做法:每次插入一个x, 会影响到gcd为x的约数的集合的数量,如果要分别更新出每一种集合的数量,需要
O(m∗约数个数2)
, TLE了
但由于我们很容易算出有多少个集合的gcd是d的倍数
F[d]
,所以我们可以计算
而每次插入一个x,我们影响到的F[i],只有x的约数项,复杂度 O(m∗约数个数)
http://paste.ubuntu.com/25023319/
部分题目
HDU 6134 Battlestation Operational
题意:求
做法:
为了方便起见,引入两个二参数的函数
可以发现 g(n,1)=f(n) G(n,x)=G(⌊nx⌋,1)
函数 G 和函数
所以要求的 g(n,1)=∑nd=1u[d]G(n,d)
反思:
赛场上CC是给出了到这里的式子的,但是我这里的函数名g(n,x)他是用f(x)给出的,一来和题目给的函数名重了,二来我比赛的时候脑子也很混,难以分清楚n在函数中的地位到底是一个参数还是一个定量。故遇到mobius的题目,为了帮助自己尽快理清思路,我认为应该设一个多元函数出来。
SPOJ Trending GCD
题意:求
做法:
对于每一个是 square free 的x 算出有哪些ab对的最大公因数是x
设
这两个式子很显然 mobius 求 f(A,B,x) 最后
再对以上过程做一些贡献优化之类的
反思:
1. 这道题因为发现有 gcd(a,b) , 然后之前做了一些 gcd 值的求和问题,都是用 phi 函数做的。一开始就不停地试图往这个上面去想,但是欧拉函数似乎只适用于不管 gcd(a,b) 是多少都要统计进去的题目。
2. AC后十天就完全无法想起这道题的思路,没有主动想过从枚举 gcd 值计算来下手,之后要牢牢记住这个思路。