模拟赛01 T3 盖房子
题面
http://zhengruioi.com/problem/248
题解
三重容斥(说是两重也行吧)
我们来看题目的约束
①有k个位置不能放(k≤8)
②每行每列至少一个
③正负对角线至少一个
④正好放n个
首先对于约束① 我们用$2^k$的容斥 也就是枚举$2^k$种放的方式,算出来之后加加减减就行了
对于约束③ 我们枚举每条对角线能不能放 然后solve(1,1)-solve(1,0)-solve(0,1)+solve(0,0)就是答案 1表示能放,0表示不能放
然后问题变成了
在一个格子图上,有$k$个点已经放上房子$(1 \leq k \leq 8)$,主对角线和副对角线有一些不能放房子,问每行每列正好放一个,一共放$n$个房子的方案数
我们把已经放上格子的去掉,并且把那一行和那一列都去掉,这样对角线可能会变成扭曲的形状,但是就没有了已经放上房子的条件
然后我们把行列交换 因为无论怎么交换一整行或者一整列,都不影响答案 交换之后我们使得主对角线和副对角线上相互影响的格子放到一起
例子:
我们这样做:
先不删格子 然后把第n行放到第一行下面,第n-1行放到第二行下面……
然后把第n列放到第一列右边,第n-1列放到第二列右边……
这样我们可以把互相影响的四个格子并起来 变成从左上角到右下角一堆2*2的格子 可能加上一个单独的格子(n为奇数)
然后再删格子
我们用f[i][j]表示当前考虑到第i个“格子的并”,当前放了j个房子,然后看第i个“格子的并”能放几个房子(0~2个),更新答案
然后我们就得到$f[cnt][k]*A_{m-k}^{n-k}$表示在这个图里,假设n<=m,对角线上放k个房子的方案数
这样再加一加,算一算就得到了答案