容斥原理

容斥原理主要有三种题型:小学生容斥,合法的方案数,...等于k的方案数。
大体思路是先利用各种稀奇古怪的方法求出包含不合法或者重复计算了的,但是比较好求的东西,然后套以下三种方法:
小学生容斥就是统计一些东西,再减去重复统计的。
合法的方案数就是ans1-ans2+ans3-ans4……
等于k的方案数就是
  for (int i=n;i>k;i--)
     for (int j=1;j<=i-1;j++)
        ans[j]-=ans[i]*C[i][j];
有一个不明白的问题就是为什么不能直接ans[k]-ans[k+1]*C[k+1][k]
等于k的O(n)做法:
for (int i=n;i>=k;i--)
{
int ty=((i-k)&1)?-1:1;
sum+=ty*C(i,k)*ans[i];
}

小学生容斥:
bzoj 3235 好方的蛇 
        利用单调队列求出以(x,y)为左上角、左下角、右上角、右下角的矩形个数,计算以(i,j)为左上角的矩形与在[i,n],[j,m]范围之外的矩形配对的答案,由于处在左下和右上的矩形会被计算两次,要减去

合法的方案数:
bzoj 1853 幸运数字
       预处理出只含86的数字,枚举这些数的子集,计算区间内子集中的数的最小公倍数的出现次数,按子集的大小奇加偶减。还有一道crash的算术教室也是这种思路
bzoj 1042 硬币购物
      预处理出不考虑用超每种价格的方案数,f[i]表示价格为i的方案数,由于不使用使用sum的东西装满体积v背包的方案数等于装满体积v-sum的方案数,我们只需要利用容斥原理,-一种超标+两种超标-3种超标+四种超标。

......等于k的方案数
bzoj 3198 spring
n个长度为7的数列中恰有k个数相等的数列对数
枚举子集,利用hash表求出集合内的位置相等的数列的对数,加到ans[子集的大小]中,利用组合容斥解决。这道题的hash冲突的概率很大,所以要用链表来存hash。
bzoj 3622 已经没有什么可害怕的了
两个数组排序后,处理出next[i]表示满足tang[i]>yao[j]的最大的j。
f[i][j]前i种糖果,有j个糖比药多,不考虑剩余情况的方案数//也就是剩余n-j个糖果的放法算一种,最后乘上阶乘。
f[i][j]=f[i-1][j]+f[i-1][j-1]*max(next[i]-j+1,0) 开始忘记max了。因为f[i][j]不一定都是合法状态,所以要判一下。
套容斥
bzoj 2839 集合计数
设状态为交集大于等于k个的方案数。
f[i]=C(n,k)*[2^(2^(n-i))-1];

你可能感兴趣的:(容斥原理)