容斥原理/莫比乌斯反演破译密码

Posted skywalker767

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了容斥原理/莫比乌斯反演破译密码相关的知识,希望对你有一定的参考价值。

重学了一下莫反,感觉收获了好多。(原来你还记得自己学过莫反

原题链接:https://www.acwing.com/problem/content/217/
题目描述

达达正在破解一段密码,他需要回答很多类似的问题:
对于给定的整数 a,b 和 d,有多少正整数对 x,y,满足 x≤a,y≤b,并且 gcd(x,y)=d。作为达达的同学,达达希望得到你的帮助。

我们分析一下,题目很明了,要求的就是 g c d ( x , y ) = d gcd(x , y) = d gcd(x,y)=d的个数,转化一下:
x ′ = x / d , y ′ = y / d [ g c d ( x , y ) = d ] = [ g c d ( x ′ , y ′ ) = 1 ] x' = x / d , y' = y / d\\\\ [gcd(x , y) = d] = [gcd(x' , y') = 1]\\\\ x=x/d,y=y/d[gcd(x,y)=d]=[gcd(x,y)=1]
这两个是等价的,但是看的时候我还是愣了一下(还是比较笨的),但是仔细思考下,感觉还是很容易证明的。

证明:
首先,x , y 的最大公约数是d,那么我们除去最大公约数,两个数就互质了,这个毋庸置疑,对于每个 g c d ( x , y ) = d gcd(x , y) = d gcd(x,y)=d都如此操作,那么可以证明,这两个的数量是一一对应的。
(这么显然,我还要思考一会,真滴笨!OVQ)


那么我们的问题转化为: x ≤ a / d x \\le a/d xa/d , y ≤ b / d y \\le b/d yb/d g c d ( x , y ) = 1 gcd(x , y)= 1 gcd(x,y)=1的个数,我们考虑容斥原理:互质的数 = 总数 - 不是互质的数,
总数很容易, a ′ = a / d , b ′ = b / d a' = a / d , b' = b / d a=a/d,b=b/d , 那么总数就是 a ′ ∗ b ′ a' * b' ab,下面分析下我们要减去的不互质的数:
∑ i = 2 m i n ( a , b ) [ a ′ i ] ∗ [ b ′ i ] ∗ m o b i u s [ i ] ∑^min(a,b)_i=2 [\\fraca'i]∗[\\fracb'i]∗mobius[i] i=2min(a,b)[ia][ib]mobius[i]
式子上午看的,人是上午没的,我直接喵喵喵?? 愣了一会,发现显然(我是笨比).

证明
我们要减去的是什么呢?是不互质的数,不互质数是什么呢?是最大公因数不为1的数,不为1,那可以为几呢?不是1就行(废话),我们枚举最大公因数不为1的个数即可。枚举每一个可能的最大公因数,并且计算个数。
当最大公因数是只有一个质因子的时候,我们可以列出:
[ a ′ 2 ] ∗ [ b ′ 2 ] + [ a ′ 3 ] ∗ [ b ′ 3 ] + . . . . . [\\fraca'2] * [\\fracb'2] + [\\fraca'3] * [\\fracb'3] + ..... [2a][2b]+[3a][3b]+.....
最大公因数是2的两对数,实际上就等2的倍数个数相乘, 这两个个数是等同的,同理3也是,但是我们要考虑重复的情况,如6,我们2,3,都枚举了一次,那么会重复,根据容斥原理,我们要减去,最后我们发现,其实符号就是 M o b i u s Mobius Mobius函数(这个证明是显然的)。以此类推,枚举到 a ′ a' a b ′ b' b中较小的就可以了,因为大于较小的,则式子为0,我们就能推出上面的式子了。(被自己蠢哭了)

那么答案呼之欲出:
a ′ b ′ + ∑ i = 2 m i n ( a , b ) [ a ′ i ] ∗ [ b ′ i ] ∗ m o b i u s [ i ] a'b' + ∑^min(a,b)_i=2 [\\fraca'i]∗[\\fracb'i]∗mobius[i]\\\\ ab+i=2min(a,b)[ia][ib]mobius[i]

我们把这玩意合体一下
∑ i = 1 m i n ( a , b ) [ a ′ i ] ∗ [ b ′ i ] ∗ m o b i u s [ i ] ∑^min(a,b)_i=1 [\\fraca'i]∗[\\fracb'i]∗mobius[i] i=1min(a,b)[ia][ib]mobius[i]

(当当当当!)

然后我们发现,高兴的还是有点早,每次都是 O ( n ) O(n) O(n),总体是 O ( n 2 ) O(n^2) O(n2)时间复杂度很大,我们忍受不了。

然后神奇的东西就出现了,我们称之为 “优雅的暴力——分块”
下面来分析下分块,这个还好!没怎么卡。

首先,我们发现式子里面有很多取整,那么实际上数据应该是一段一段的,我们就可以考虑通过这点来加速,既然这一段都是一样的,我们直接一段一段的算,发现效率可观,可以达到 O ( n n ) ) O(n\\sqrtn) ) O(nn )),下面写下分块的原理,我们定义一个 get(x) 函数,这个函数和lowbit函数一样,虽然短小,但是精悍,他主要做的事是:传回当前一样的一段中,下标最大的那个,也就是 a g e t ( x ) + 1 \\fracaget(x) + 1 get(x)+1a就会变小。

int get(int n , int x) 
	return n / (n / x);

我们说这玩意想着就是一段一段的,那么到底多少呢?答案是: 2 a 2\\sqrta 2a

证明: 我们把1到n分成:1到 a \\sqrta a a + 1 \\sqrta + 1 a +1 n n n,我们发现 a 1 ∼ a \\fraca1 \\sim \\sqrta 1a a,只有 a \\sqrta a poj3904-Sky Code-一起揭露莫比乌斯反演和容斥的一致性

BZOJ 2440: [中山市选2011]完全平方数 二分答案 + 容斥原理 + 莫比乌斯反演

CF900DUnusual Sequences 容斥(莫比乌斯反演)

A - Visible Lattice Points SPOJ - VLATTICE 容斥原理/莫比乌斯反演

[HAOI2011][bzoj2301] Problem b [莫比乌斯反演+容斥原理+分块前缀和优化]

(HDU 1695)GCD(容斥+莫比乌斯反演)