【做题】51NOD1518 稳定多米诺覆盖——容斥&dp
题意:求有多少种方案,用多米诺骨牌覆盖一个\(n\times m\)的棋盘,满足任意一对相邻行和列都至少有一个骨牌横跨。对\(10^9+7\)取模。
\(n,m \leq 16\)
首先,这个问题的约束比较复杂,直接dp需要较高的代价记录状态,不能通过本题。
然而,这个问题的约束可以被拆分为多个小约束(某条线被横跨),且小约束可以直接合并。这启发我们使用容斥。
这样,我们的dp计数就简化为了固定几条线不被跨越后任意覆盖。设\(f_k\)为恰有\(k\)条线不被跨越的方案数,\(g_k\)为我们计算出的固定了\(k\)条线后的覆盖方案数。那么,我们有
\]
由二项式反演可得
\]
剩下的问题就在于计算所有\(g_k\)了。我们不能枚举所有要被跨越的线,但是枚举一维之后,另一维就可以dp了。假设我们已经枚举了列上的线,令\(dp_{i,j}\)表示前\(i\)行有\(j\)条线没有跨越的方案数,暴力转移。通过预处理能做到\(O(n^3)\)。而考虑到状态中的\(j\)至于最后\(-1\)的指数有关,故可以省去。因此这个dp是\(O(n^2)\)的。
时间复杂度\(O(n^2 2^n)\)。
#include <bits/stdc++.h>
using namespace std;
const int N = 20, MOD = (int)(1e9 + 7), MAX = 16;
int n,m,dp[2][1 << MAX],f[N][N],ans,g[N],rec[N];
typedef long long ll;
void doit(int wd) {
memset(dp,0,sizeof dp);
int p = 1, lim = (1 << wd) - 1;
dp[0][(1 << wd)-1] = 1;
for (int i = 1 ; i <= n ; ++ i) {
for (int j = 1 ; j <= wd ; ++ j, p ^= 1) {
memset(dp[p],0,sizeof dp[p]);
for (int s = 0 ; s < (1 << wd) ; ++ s) {
if (((s >> (wd-1))&1) == 0)
(dp[p][(s << 1 | 1) & lim] += dp[p^1][s]) %= MOD;
else {
if ((!(s&1)) && j != 1) (dp[p][(s << 1 | 3) & lim] += dp[p^1][s]) %= MOD;
(dp[p][(s << 1) & lim] += dp[p^1][s]) %= MOD;
}
}
}
f[i][wd] = dp[p^1][lim];
}
}
void prework() {
for (int i = 1 ; i <= m ; ++ i)
doit(i);
}
vector<int> tmp;
int main() {
n = m = 16;
prework();
while (scanf("%d%d",&n,&m) != EOF) {
ans = 0;
for (int s = (1 << m >> 1) ; s < (1 << m) ; ++ s) {
tmp.clear();
int las = 0;
for (int i = 1 ; i <= m ; ++ i)
if ((s >> (i-1))&1) tmp.push_back(i-las), las = i;
for (int i = 1 ; i <= n ; ++ i) {
rec[i] = 1;
for (int j = 0 ; j < (int)tmp.size() ; ++ j)
rec[i] = 1ll * rec[i] * f[i][tmp[j]] % MOD;
}
memset(g,0,sizeof g);
for (int i = 1 ; i <= n ; ++ i) {
g[i] = rec[i];
for (int k = 1 ; k < i ; ++ k)
(g[i] += -1ll * rec[i-k] * g[k] % MOD) %= MOD;
}
if (tmp.size()&1) (ans += g[n]) %= MOD;
else (ans -= g[n]) %= MOD;
}
ans = (ans % MOD + MOD) % MOD;
printf("%d\n",ans);
}
return 0;
}
小结:本题的关键在于想到容斥,以及枚举一维后dp另一维。这两个思路都有较广的适用性,有必要熟练运用。
【做题】51NOD1518 稳定多米诺覆盖——容斥&dp的更多相关文章
- 51Nod1518 稳定多米诺覆盖 动态规划 插头dp 容斥原理
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1518.html 题目传送门 - 51Nod1518 题意 51Nod真是个好OJ ,题意概括的真好, ...
- 51nod 1518 稳定多米诺覆盖(容斥+二项式反演+状压dp)
[传送门[(http://www.51nod.com/Challenge/Problem.html#!#problemId=1518) 解题思路 直接算不好算,考虑容斥,但并不能把行和列一起加进去容斥 ...
- Luogu P2595 [ZJOI2009]多米诺骨牌 容斥,枚举,插头dp,轮廓线dp
真的是个好(毒)题(瘤).其中枚举的思想尤其值得借鉴. \(40pts\):插头\(dp\),记录插头的同时记录每一列的连接状况,复杂度\(O(N*M*2^{n + m} )\). \(100pts\ ...
- P1282 多米诺骨牌 (差值DP+背包)
题目描述 多米诺骨牌有上下2个方块组成,每个方块中有1~6个点.现有排成行的 上方块中点数之和记为S1,下方块中点数之和记为S2,它们的差为|S1-S2|.例如在图8-1中,S1=6+1+1+1=9, ...
- jzoj5987. 【WC2019模拟2019.1.4】仙人掌毒题 (树链剖分+概率期望+容斥)
题面 题解 又一道全场切的题目我连题目都没看懂--细节真多-- 先考虑怎么维护仙人掌.在线可以用LCT,或者像我代码里先离线,并按时间求出一棵最小生成树(或者一个森林),然后树链剖分.如果一条边不是生 ...
- 【做题】POI2011R1 - Plot——最小圆覆盖&倍增
原文链接 https://www.cnblogs.com/cly-none/p/loj2159.html 题意:给出\(n\)个点,你需要按编号将其划分成不超过\(m\)段连续的区间,使得所有每个区间 ...
- 【做题】TCSRM601 Div1 500 WinterAndSnowmen——按位考虑&dp
原文链接https://www.cnblogs.com/cly-none/p/9695526.html 题意:求有多少对集合\(S,T\)满足:\(S \subseteq \{1,2...n \}, ...
- 【做题】uoj#370滑稽树上滑稽果——巧妙dp
一个显然的结论是最终树的形态必然是一条链.具体证明只要考虑选定树上的某一条链,然后把其他部分全部接在它后面,这样答案一定不会变劣. 那么,一开始的想法是考虑每一位的最后出现位置,但这并不容易实现.注意 ...
- 洛谷P1282 多米诺骨牌【线性dp】
题目:https://www.luogu.org/problemnew/show/P1282 题意: 给定n个牌,每个牌有一个上点数和下点数.可以通过旋转改变交换上下点数. 问使得上点数之和和下点数之 ...
随机推荐
- I Count Tow Three
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#inclu ...
- hdu5441 并查集+克鲁斯卡尔算法
这题计算 一张图上 能走的 点对有多少个 对于每个限制边权 , 对每条边排序,对每个查询排序 然后边做克鲁斯卡尔算法 的时候变计算就好了 #include <iostream> #inc ...
- Operation(Swift)
介绍: NSOperation需要配合NSOperationQueue来实现多线程.因为默认情况下,NSOperation单独使用时系统同步执行操作,并没有开辟新线程的能力,只有配合NSOperati ...
- windows环境下 curl 安装和使用
curl下载地址:https://curl.haxx.se/download.html,拉到页面最底下,选择红色选中的那个CAB的进行下载,如下图所示: 下载完成后,解压. 解决windows控制台c ...
- Codeforces 268B - Buttons
Manao is trying to open a rather challenging lock. The lock has n buttons on it and to open it, you ...
- python 实现有序字典
python 实现有序字典 Python默认的字典,是不按顺序存储.输出我们添加在字典中的内容的,即是无序的字典.python 使用OrderedDict函数实现有序的字典. 示例: d = dict ...
- vue 去掉路由中的#
在router.js中修改, const router = new VueRouter({ mode: 'history', routes: [...] })
- The Little Prince-12/08
The Little Prince-12/08 今天来点中文的经典语录+内心独白好不好呢? 狐狸说:“对我来说,你只是一个小男孩,就像其他成千上万个小男孩一样没有什么两样.我不需要你.你也不需要我.对 ...
- Capture HTML Canvas as gif/jpg/png/pdf?
https://stackoverflow.com/questions/923885/capture-html-canvas-as-gif-jpg-png-pdf https://stackoverf ...
- PyTorch 常用方法总结1:生成随机数Tensor的方法汇总(标准分布、正态分布……)
在使用PyTorch做实验时经常会用到生成随机数Tensor的方法,比如: torch.rand() torch.randn() torch.normal() torch.linespace() 在很 ...