传送门

很妙的题

首先先考虑一个简化的问题,现在有一行格子让你填

你要么填一格 要么填两格 有的格子不让你填 问你填了 $a$ 个一格和填了 $b$ 个两格有多少种方案

那么显然先只考虑放两格的方案,这个可以简单 $dp$ 得到,设 $f[i][j]$ 表示前 $i$ 个格子放了 $j$ 个两格的方案数

那么如果 $i,i-1$ 都没障碍,那么 $f[i][j]=f[i-1][j]+f[i-2][j-1]$ ,否则 $f[i][j]=f[i-1][j]$

然后再来考虑填一格的,显然剩下的 $tot-2j$ 个位置都可以随便填,那么方案数为 $C[tot-2j][i]$ ,直接乘法原理乘起来即可

接下来可以考虑怎么把这道题简化到这个情况,假设放了 $a$ 个水平的多米诺,$b$ 个垂直的多米诺

对于行来说,相当于放 $a$ 个 $1$ ,$b$ 个 $2$,对于列就相当于放 $a$ 个 $2$ ,$b$ 个 $1$

注意到每个多米诺可以根据在第几行和第几列来唯一确定,所以我们对行列分别求一下之前那个东西然后乘起来再乘上 $a!b!$ 即可

乘上 $a!b!$ 就相当于把骨牌不同的放置顺序看成不同的放置方案,意思是强制行的第 $i$ 个放置和列的第 $i$ 个放置配对

就原本一维的方案我们让它放置有顺序,然后强制行和列两两匹配,这样才能确定二维平面上的具体位置

因为如果只是行列乘起来,那么没法确定某个骨牌的具体位置,考虑对于 $a$ ,行放了位置 $1,3$ ,列放了位置 $(1,2),(3,4)$

那么多米诺骨牌可以是 $((1,1),(1,2))$ 和 $((3,3),(3,4))$ ,但是也有可能是 $((1,3),(1,4))$ 和 $((3,1),(3,2))$

自己画画图就很容易理解了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=,mo=;
inline int fk(int x) { return x>=mo ? x-mo : x; }
int n,m,K,Ans,fac[N],C[N][N];
int f[N][N],g[N][N];
bool px[N],py[N];
int main()
{
n=read(),m=read(),K=read(); int mx=max(n,m);
fac[]=; for(int i=;i<=mx;i++) fac[i]=1ll*fac[i-]*i%mo;
for(int i=;i<=mx;i++)
{
C[i][]=;
for(int j=;j<=i;j++)
C[i][j]=fk(C[i-][j-]+C[i-][j]);
}
for(int i=;i<=K;i++)
{
int a=read(),b=read(),c=read(),d=read();
px[a]=px[c]=; py[b]=py[d]=;
}
int cntx=,cnty=;
for(int i=;i<=n;i++) cntx+=px[i];
for(int i=;i<=m;i++) cnty+=py[i];
for(int i=;i<=n;i++) f[i][]=;
for(int i=;i<=n;i++)
for(int j=;j<=mx;j++)
if(px[i]||px[i-]) f[i][j]=f[i-][j];
else f[i][j]=fk(f[i-][j]+f[i-][j-]);
for(int i=;i<=m;i++) g[i][]=;
for(int i=;i<=m;i++)
for(int j=;j<=mx;j++)
if(py[i]||py[i-]) g[i][j]=g[i-][j];
else g[i][j]=fk(g[i-][j]+g[i-][j-]);
for(int i=;i<=mx;i++)
for(int j=;j<=mx;j++)
if(i+j*<=n-cntx&&i*+j<=m-cnty)
Ans=fk(Ans + 1ll*f[n][j]*C[n-cntx-j*][i]%mo *g[m][i]%mo *C[m-cnty-i*][j]%mo *fac[i]%mo *fac[j]%mo );
printf("%d\n",Ans);
return ;
}

Codeforces 1237F. Balanced Domino Placements的更多相关文章

  1. CF1237F Balanced Domino Placements

    题意 给定一个 \(h\) 行 \(w\) 列的方格图,上面已经放置了一些 \(1\times 2\) 的多米诺骨牌. 我们称一个放置多米诺骨牌的方案是好的,当且仅当任何两个多米诺骨牌不占用相同的行与 ...

  2. [Codeforces 873B]Balanced Substring

    Description You are given a string s consisting only of characters 0 and 1. A substring [l, r] of s  ...

  3. CodeForces - 873B Balanced Substring(思维)

    inputstandard input outputstandard output You are given a string s consisting only of characters 0 a ...

  4. Codeforces 873B - Balanced Substring(思维)

    题目链接:http://codeforces.com/problemset/problem/873/B 题目大意:一个字符串全部由‘0’和‘1’组成,当一段区间[l,r]内的‘0’和‘1’个数相等,则 ...

  5. Codeforces 1237E. Balanced Binary Search Trees

    传送门 这一题是真的坑人,时间空间都在鼓励你用 $NTT$ 优化 $dp$...(但是我并不会 $NTT$) 看到题目然后考虑树形 $dp$ ,设 $f[i][0/1]$ 表示 $i$ 个节点的树,根 ...

  6. Codeforces 1237D. Balanced Playlist

    传送门 首先显然的,如果一个位置开始播放了两圈还没结束,那么就永远不会结束 先考虑位置 $1$ 开始播放,用一个 $multisetset$ 维护一下当前听的所有歌,直到某一首歌 $r$ 不合法了就停 ...

  7. Codeforces 1237C2. Balanced Removals (Harder)

    传送门 先来考虑一下二维时的情况,那么对于 $x$ 相同的点,我们按 $y$ 排序,然后相邻的一对对消除 最后 $x$ 坐标相同的点最多剩下一个,那么此时所有点的 $x$ 坐标都不一样 再按 $x$ ...

  8. Codeforces 1237B. Balanced Tunnel

    传送门 这一题有点意思 首先预处理出 $pos[x]$ 表示编号 $x$ 的车是第几个出隧道的 然后按进入隧道的顺序枚举每辆车 $x$ 考虑有哪些车比 $x$ 晚进入隧道却比 $x$ 早出隧道 显然是 ...

  9. Codeforces Good Bye 2015 C. New Year and Domino 前缀和

    C. New Year and Domino 题目连接: http://www.codeforces.com/contest/611/problem/C Description They say &q ...

随机推荐

  1. 预处理、const、static与sizeof-使用const与#define的特点及区别

    1:#define只是用来做文本替换的.例如: #define PI 3.1415926 float angle; angle=*PI/; 那么,程序进行编译的时候,编译器会首先将“#define P ...

  2. FutureTask用法及解析

    1 FutureTask概念 FutureTask一个可取消的异步计算,FutureTask 实现了Future的基本方法,提空 start cancel 操作,可以查询计算是否已经完成,并且可以获取 ...

  3. 1.3 Go语言基础之数据类型

    Go语言中有丰富的数据类型,除了基本的整型.浮点型.布尔型.字符串外,还有数组.切片.结构体.函数.map.通道(channel)等.Go 语言的基本类型和其他语言大同小异. 一.整型 1.1 基本类 ...

  4. Java同步数据结构之ArrayBlockingQueue

    引言 作为BlockingQueue最常见的实现类之一,ArrayBlockingQueue是通过数组实现的FIFO先进先出有界阻塞队列,它的大小在实例被初始化的时候就被固定了,不能更改.该类支持一个 ...

  5. 使用Jsp/Js/Ajax/Json/Jquery/Easyui + Servlet + JDBC + Lucene/Mysql/Oracle完成数据库分页

    package loaderman.action; import java.io.IOException; import java.io.PrintWriter; import java.util.L ...

  6. C标准库中转换wchar_t和char类型的字符串

    C 库函数 - mbstowcs()  C 标准库 - <stdlib.h> 描述 C 库函数 size_t mbstowcs(schar_t *pwcs, const char *str ...

  7. an extra named object property

    Grunt supports the ability to split each task configuration into several separate configurations all ...

  8. 小D课堂-SpringBoot 2.x微信支付在线教育网站项目实战_2-1.快速搭建SpringBoot项目,采用Eclipse

    笔记 1.快速搭建SpringBoot项目,采用Eclipse     简介:使用SpringBoot start在线生成项目基本框架并导入到eclipse中 1.站点地址:http://start. ...

  9. 你应该知道的 MySQL 的锁

    背景 数据库的锁是在多线程高并发的情况下用来保证数据稳定性和一致性的一种机制.MySQL 根据底层存储引擎的不同,锁的支持粒度和实现机制也不同.MyISAM 只支持表锁,InnoDB 支持行锁和表锁. ...

  10. 包含min函数的栈、队列

    题目:定义栈的数据结构,请在该类型中实现一个能够得到栈/队列的最小元素的min函数.在该栈/队列中,调用min.入栈(入队列)及出栈(出队列)函数的时间复杂度都是O(1). 1. 包含min函数的栈 ...