zoukankan      html  css  js  c++  java
  • CF1237F Balanced Domino Placements 题解

    Codeforces
    Luogu

    Description.

    \(n\times m\) 的网格,放了 \(k\) 个骨牌。
    在剩下填若干个骨牌,没有一行有两个被骨牌覆盖的格子,没有一列有两个被骨牌覆盖的格子。

    Solution.

    首先考虑一个非常 Naive 的做法,就是把所有被覆盖的删掉,然后统计方案数。
    这个非常非常 Naive,因为删掉后相邻的格子不一定在删掉前相邻。

    这提示我们相邻的格子是本题最难处理的地方,可以考虑预处理。
    相邻的格子分为两类:行相邻和列相邻,而且显然可以拆开。
    转化为一个很 Naive 的子问题:有一个序列已经染黑,求染黑 \(k\) 对相邻格子的方案数。
    这个很显然直接序列 dp 就行了。

    接下来考虑枚举 \(i\) 个横放骨牌和 \(j\) 个竖放骨牌,直接两两匹配。
    除了已经染黑的格子之外全都可以当作染黑格子,所以就是一个排列数。
    式子大概是 \(\sum_{i=0}\sum_{j=0}f_{n,i}\times g_{m,j}\times (c_0-i)^{\underline j}\times (c_1-j)^{\underline j}\)

    Coding.

    点击查看代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    const int N=3605,P=998244353;
    int fc[N],fi[N],iv[N];//dbinit{{{
    inline int ksm(int x,int q=P-2) {int r=1;for(;q;q>>=1,x=1ll*x*x%P) if(q&1) r=1ll*r*x%P;return r;}
    inline void dbinit(int n=N-1)
    {
    	fc[0]=1;for(int i=1;i<=n;i++) fc[i]=1ll*fc[i-1]*i%P;
    	iv[1]=1;for(int i=2;i<=n;i++) iv[i]=1ll*iv[P%i]*(P-P/i)%P;
    	fi[0]=1;for(int i=1;i<=n;i++) fi[i]=1ll*fi[i-1]*iv[i]%P;
    }
    inline int C(int n,int m) {return n<0||m<0||n<m?0:1ll*fc[n]*fi[m]%P*fi[n-m]%P;}//}}}
    int n,m,K,f[N][N],g[N][N];char vx[N],vy[N];
    int main()
    {
    	read(n,m,K);for(int i=1,x,y,a,b;i<=K;i++) read(a,x,b,y),vx[a]=vx[b]=vy[x]=vy[y]=1;
    	vx[0]=1,f[0][0]=1;for(int i=1;i<=n;i++) for(int j=0;j<=n/2;j++)
    		if(vx[i]||vx[i-1]) f[i][j]=f[i-1][j];else f[i][j]=(f[i-1][j]+(j?f[i-2][j-1]:0))%P;
    	vy[0]=1,g[0][0]=1;for(int i=1;i<=m;i++) for(int j=0;j<=m/2;j++)
    		if(vy[i]||vy[i-1]) g[i][j]=g[i-1][j];else g[i][j]=(g[i-1][j]+(j?g[i-2][j-1]:0))%P;
    	dbinit();int rs=0,c1=n,c2=m;
    	for(int i=1;i<=n;i++) c1-=vx[i];
    	for(int i=1;i<=m;i++) c2-=vy[i];
    	for(int i=0;i*2<=c1;i++) for(int j=0;j*2<=c2-i&&j<=c1-i*2;j++)
    		rs=(rs+1ll*f[n][i]*g[m][j]%P*fc[c2-j*2]%P*fi[c2-j*2-i]%P*fc[c1-i*2]%P*fi[c1-i*2-j])%P;
    	return printf("%d\n",rs),0;
    }
    
  • 相关阅读:
    javascript语法之函数案例练习
    javascript语法之函数的定义
    javascript语法之with语句
    javascript语法之for-in语句
    javascript语法之循环语句小练习
    centos 7 配置samba mount
    Centos 7 systemd.service — Service unit configuration
    Linux 下使用 ffmpeg 大批量合并 ts 文件, mp4切割文件为m3u8
    Debian 系统修改网卡ens33名称为 eth0
    star_namelist
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15425724.html
Copyright © 2011-2022 走看看