[传送门[(http://www.51nod.com/Challenge/Problem.html#!#problemId=1518)

解题思路

  直接算不好算,考虑容斥,但并不能把行和列一起加进去容斥,这会使时间复杂度非常高,那么就考虑枚举行后\(dp\)。设\(f[i]\)表示存在\(i\)列有线,任意一行无线的方案数,\(g[i[\)表示至少有\(i\)列有线,任意一行无线的方案数,那么

\[g[i]=\sum\limits_{k=i}^n C(i,k)f[i]
\]

二项式反演得

\[f[0]=\sum\limits_{k=0}^n(-1)^kg[k]C(k,0)
\]

那么只需要考虑求出\(g\)。

  首先要预处理出来\(dp[i][j]\)表示\(i\)行\(j\)列任意放的方案数,那么算答案时可以先枚举哪几列有线,然后算出\(g[i]\),\(g[i]\)就是首先把\(dp\)数组合并,直观理解就是把那几块拼在一起,然后减去\(j<i\)的\(g[j]\),就是保证行没有线,之后就可以算答案了。时间复杂度O(\(2^n n^2)\)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#define int long long using namespace std;
const int N=18;
const int MOD=1e9+7;
typedef long long LL; int f[N][N],n,m,g[N],ans,dp[2][(1<<(17))],tmp[N];
vector<int> v; inline void DP(int lim){
memset(dp,0,sizeof(dp));
int now=0; dp[0][(1<<lim)-1]=1;
for(int i=1;i<=n;i++){
for(int j=1;j<=lim;j++){
now^=1; memset(dp[now],0,sizeof(dp[now]));
for(int S=0;S<(1<<lim);S++)if(dp[now^1][S]){
if(S&1) (dp[now][S>>1]+=dp[now^1][S])%=MOD;
if(i!=1 && (!(S&1)))
(dp[now][(S>>1)|(1<<(lim-1))]+=dp[now^1][S])%=MOD;
if(j!=1 && (S&1) && lim>1 && (!(S&(1<<(lim-1)))))
(dp[now][(S>>1)|(1<<(lim-1))|(1<<(lim-2))]+=dp[now^1][S])%=MOD;
}
}
f[i][lim]=dp[now][(1<<lim)-1];
}
} inline void prework(){
for(int i=1;i<=m;i++) DP(i);
} signed main(){
n=m=16; prework();
while(~scanf("%lld%lld",&n,&m)){
for(int S=(1<<(m-1));S<(1<<m);S++){
int lst=0; v.clear();
for(int i=1;i<=m;i++)
if(S&(1<<(i-1))) v.push_back(i-lst),lst=i;
for(int i=1;i<=n;i++){
tmp[i]=1;
for(int j=0;j<v.size();j++)
tmp[i]=1ll*tmp[i]*f[i][v[j]]%MOD;
}
for(int i=1;i<=n;i++){
g[i]=tmp[i];
for(int k=1;k<i;k++)
g[i]-=1ll*g[k]*tmp[i-k]%MOD,g[i]%=MOD;
}
if(v.size()&1) (ans+=g[n])%=MOD;
else (ans-=g[n])%=MOD;
} ans=(ans%MOD+MOD)%MOD;
printf("%lld\n",ans); ans=0;
}
return 0;
}

51nod 1518 稳定多米诺覆盖(容斥+二项式反演+状压dp)的更多相关文章

  1. 【做题】51NOD1518 稳定多米诺覆盖——容斥&dp

    题意:求有多少种方案,用多米诺骨牌覆盖一个\(n\times m\)的棋盘,满足任意一对相邻行和列都至少有一个骨牌横跨.对\(10^9+7\)取模. \(n,m \leq 16\) 首先,这个问题的约 ...

  2. Luogu P2595 [ZJOI2009]多米诺骨牌 容斥,枚举,插头dp,轮廓线dp

    真的是个好(毒)题(瘤).其中枚举的思想尤其值得借鉴. \(40pts\):插头\(dp\),记录插头的同时记录每一列的连接状况,复杂度\(O(N*M*2^{n + m} )\). \(100pts\ ...

  3. 【题解】[HAOI2018]染色(NTT+容斥/二项式反演)

    [题解][HAOI2018]染色(NTT+容斥/二项式反演) 可以直接写出式子: \[ f(x)={m \choose x}n!{(\dfrac 1 {(Sx)!})}^x(m-x)^{n-Sx}\d ...

  4. 51Nod1518 稳定多米诺覆盖 动态规划 插头dp 容斥原理

    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1518.html 题目传送门 - 51Nod1518 题意 51Nod真是个好OJ ,题意概括的真好, ...

  5. NOI Online 游戏 树形dp 广义容斥/二项式反演

    LINK:游戏 还是过于弱鸡 没看出来是个二项式反演,虽然学过一遍 但印象不深刻. 二项式反演:有两种形式 一种是以恰好和至多的转换 一种是恰好和至少得转换. 设\(f_i\)表示至多的方案数 \(g ...

  6. 多米诺骨牌放置问题(状压DP)

    例题: 最近小A遇到了一个很有趣的问题: 现在有一个\(n\times m\)规格的桌面,我们希望用\(1 \times 2\)规格的多米诺骨牌将其覆盖. 例如,对于一个\(10 \times 11\ ...

  7. HDU5731 Solid Dominoes Tilings 状压dp+状压容斥

    题意:给定n,m的矩阵,就是求稳定的骨牌完美覆盖,也就是相邻的两行或者两列都至少有一个骨牌 分析:第一步: 如果是单单求骨牌完美覆盖,请先去学基础的插头dp(其实也是基础的状压dp)骨牌覆盖 hiho ...

  8. bzoj2669[cqoi2012]局部极小值 容斥+状压dp

    2669: [cqoi2012]局部极小值 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 774  Solved: 411[Submit][Status ...

  9. 51nod 1673 树有几多愁——虚树+状压DP

    题目:http://www.51nod.com/Challenge/Problem.html#!#problemId=1673 建一个虚树. 一种贪心的想法是把较小的值填到叶子上,这样一个小值限制到的 ...

随机推荐

  1. String 与StringBuffer习题

    1: 画出如下几行代码的结构 // 画出如下几行代码的结构 String s1 = "hello"; // value存储在常量池内 String s2 = "hello ...

  2. tomcat 迁移到weblogic 问题

    问题1: Caused by: java.lang.UnsupportedClassVersionError: com/audaque/datadiscovery/soap/service/impl/ ...

  3. delphi 获得时间戳 毫秒数

    function DateTimeToMilliseconds(const ADateTime: TDateTime): Int64; //获得毫秒var LTimeStamp: TTimeStamp ...

  4. PHP获得计算机的唯一标识[cpu,网卡]

    以下是从网上转载来的源码,但是我测试均不能执行,不知道怎么回事,转过来大家可以交流一下 <?php//获取电脑的CPU信息 function OnlyU(){ $a = ''; $b = arr ...

  5. POJ - 3176 Cow Bowling 动态规划

    动态规划:多阶段决策问题,每步求解的问题是后面阶段问题求解的子问题,每步决策将依赖于以前步骤的决策结果.(可以用于组合优化问题) 优化原则:一个最优决策序列的任何子序列本身一定是相当于子序列初始和结束 ...

  6. typedef&define的用法与区别

    1.  typedef typedef故名思意就是类型定义的意思,但是它并不是定义一个新的类型而是给已有的类型起一个别名,在这一点上与引用的含义类似,引用是变量或对象的别名,而typedef定义的是类 ...

  7. JavaScript Tre

    function BinarySearchTree() { var Node = function(key) { this.key = key; this.left = null; this.righ ...

  8. [Linux] 013 其他文件搜索命令

    1. 文件搜索命令:locate 命令名称:locate 命令所在路径:/bin/locate 执行权限:所有用户 语法:locate 文件名 功能描述:在文件资料库中查找文件 范例: $ locat ...

  9. python 注释有哪些和作用

    python 单行注释 #作为代表 python 多行注释 ‘’‘ 这是三个单引号注释 ’‘’ “”“ 这是三个双引号注释 ”“”

  10. angularjs 信息链接 转摘自:http://www.zhihu.com/question/27427447

    这个问题嘛,真不好回答,问的太笼统了,其实你只要熟悉掌握了Angular.js,自然而然的就会用Angular.js结合自身的业务去构建SPA程序了,Angular.js是一个比较全面的框架,按照他的 ...