您的位置:首页 > 其它

容斥原理的公式推导

2018-03-28 16:09 417 查看
对于容斥原理的最简单的理解就是,把要计算的加上,然后把加多的减掉,然后再把减多的再加回去。这样循环下去就对了。

一个好理解的例子就是一个班上有三个兴趣班(c++,java,pasico),每个人都报了兴趣班。30人报了一个,12人报了两个,3人报了三个,求班上有多少人?这是一道小学题,自然也很简单。ans=30-12+3=21(人)。然后这样为什么是对的呢?我们思考一下30之中把报了两项的人计算了2次,把报了三项的人计算了3次。12中把报了3项的人计算了3次。所以我们用那个加减表示每种人都只计算1次的答案。(可以看图再理解一下)



但是并没有那么简单,因为不可能每道题的系数都是-1和1的交替。要解决更一般性的问题,我们可能要自己推系数,我们重点讲一下推系数的方法。

一般的,由总结的公式得出∑ni=1s(Ci)fi=s(C0)∑i=1ns(Ci)fi=s(C0),其中s(Ci)s(Ci)表示所有物品在满足CiCi情况下的总贡献(一般的计数问题s(Ci)s(Ci) 就是 满足条件CiCi 情况的个数),而fifi是一个系数,在计算时,我们才能把除答案以外的的贡献消掉。(这是用于计算答案的式子)要对这个公式有一个理解,我们还是举两个例子。

一、(错排问题),一串1−n1−n的数列,求对于任意ii不在第ii位排列的方案数。

对于这个问题,首先我们要构造CiCi,当然这是很简单的,我们很容易就可以想到:CiCi表示满足有至少ii个不错排数的情况。所以有:∑ni=0Cin∗fi==[n==0]∑i=0nCni∗fi==[n==0]。反正第一次看人家推这个式子是懵逼的,为啥s(Ci)s(Ci)变成一个组合数了呢?其实仔细推敲一下还是可以理解的。首先,上面的式子和下面是有区别的。也就是说,这俩货都不是一个东西。这个式子是用来计算fifi的!!!

现在大概能懂了吧,假设有一个恰好有nn个不错排数的情况,它在i=0i=0时被计算了C0nCn0次,在i=1i=1时被计算了C1nCn1次,以此类推……因为我们要求的的是错排数列,所以当n≠0n≠0时是不符合题意的,我们要让它的贡献为0(另:只有n=0n=0时,这个排列的贡献为1)。然后可以想到一个n2n2递推fifi的方法。当然这类fifi是有规律的,我们打表可知:fi=(−1)ifi=(−1)i。

至此我们把fifi全部计算出来了,之后我们怎么计算答案呢?这个时候我们就可以使用上面一个公式了。ans=∑ni=1Cin∗(n−i)!∗fians=∑i=1nCni∗(n−i)!∗fi。

是不是很神奇呢?

二、(约数问题),给定mm个数,统计在[1,n][1,n]中,有奇数个整除它的数的个数。(ii属于[1,n][1,n],若在这mm个数里,有奇数个数可以整除ii,则ansans++),m≤15m≤15,n≤1e9n≤1e9。

枚举nn的复杂度是n∗mn∗m的,显然会超时,考虑容斥。

枚举mm的子集,求lcmlcm,有了第一题的经验,我们写出式子:∑ki=0Cin∗fi=[k%2==1]∑i=0kCni∗fi=[k%2==1],(奇数时贡献为1)。对于一个约数恰好为kk个的数,它在计算至少0个约数的时候计算了C0kCk0次,在计算至少1个约数时计算了C1kCk1次,以此类推……

怎么计算答案呢?ans=∑(s∈m)nlcm(s)∗f|s|ans=∑(s∈m)nlcm(s)∗f|s|。

其实看懂了也很简单,一般求fifi的式子含组合数,当然也有可能是一些奇奇怪怪的东西,比如斯特林数什么的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: