骨牌覆盖去除切割线的情况(DP+容斥原理)

本文介绍了一种使用轮廓线DP和容斥原理解决矩阵覆盖问题的方法,通过预处理任意矩阵覆盖方案数并结合行列分割策略,高效计算出符合要求的覆盖方案总数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目要求给出N*M的矩阵,用1*2和2*1的骨牌覆盖,不出现切割线的情况有多少。

这题可以先用轮廓线DP求出任意矩阵一共有多少种放法,

预处理出任意矩形大小的方案数 RES[i][j] 
不过我怀疑这部分不提前打表的过不了

第二部分是一个容斥 
先对列容斥,用状压的方式枚举出所有列的分割情况 
然后计算,当前列分割情况下,行没有分割的方案数 dp[n] 
然后再用容斥,奇加偶减即能得出答案

而 dp[n]的求法为,设当前分割下,宽度为 x的无限制覆盖为 cnt[x] 
cnt[x]=RES[x][bsiz1]RES[x][bsiz2]...RES[x][bsizt] 
其中 bsiz1...bsizt为列分割线分割出的每一块的横向大小 
dp[i]=cnt[i]i1j=0dp[j]cnt[ij] 
其中 cnt[i]为宽度为 i的任意覆盖, 
减去每一个前 j个无行分割线,后 ij个有行分割线的方案 
减去这些互斥的非法方案,剩下的即为宽度为 i的无行分割线的合法覆盖


#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>


#define LL long long int


LL dp[17];
const int MOD = 1e9 + 7;
LL RES[17][17];
LL ANS[17][17];
int block[17];
int blocknum;


LL solve(int, int);
void Init();
int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	Init();
	int n, m;
	while (~scanf("%d %d", &n, &m))
	{
		printf("%lld\n", solve(n, m));
	}


}


LL solve(int n, int m)
{
	if ((n & 1) && (m & 1))
	{
		return 0;
	}
	LL ans = 0;
	for (int k = 0; k < (1 << (m - 1)); ++k)
	{
		int d = 1;//竖线隔开的块有多少
		blocknum = 0;//被隔开的方块数
		for (int i = 0; i < m - 1; ++i)
		{
			if (k & (1 << i))
			{
				block[blocknum++] = d;
				d = 1;
			}
			else
				++d;
		}
		block[blocknum++] = d;
		dp[0] = 0;//当前行到0行没有横线的情况
		for (int i = 1; i <= n; ++i)
		{
			LL max = 1;
			for (int j = 0; j < i; ++j)
			{
				LL t = 1;
				for (int I = 0; I < blocknum; ++I)
				{
					t = (t*RES[i - j][block[I]]) % MOD;
				}
				if (!j)
				{
					dp[i] = t;
				}
				else
				{
					dp[i] = (dp[i] - dp[j] * t) % MOD;
				}
			}
		}
		if (blocknum & 1)
			ans = (ans + dp[n]) % MOD;
		else
			ans = (ans - dp[n]) % MOD;
	}
	return (ans + MOD) % MOD;
}




void Init()
{
	RES[1][1] = 0;
	RES[1][2] = 1;
	RES[1][3] = 0;
	RES[1][4] = 1;
	RES[1][5] = 0;
	RES[1][6] = 1;
	RES[1][7] = 0;
	RES[1][8] = 1;
	RES[1][9] = 0;
	RES[1][10] = 1;
	RES[1][11] = 0;
	RES[1][12] = 1;
	RES[1][13] = 0;
	RES[1][14] = 1;
	RES[1][15] = 0;
	RES[1][16] = 1;
	RES[2][1] = 1;
	RES[2][2] = 2;
	RES[2][3] = 3;
	RES[2][4] = 5;
	RES[2][5] = 8;
	RES[2][6] = 13;
	RES[2][7] = 21;
	RES[2][8] = 34;
	RES[2][9] = 55;
	RES[2][10] = 89;
	RES[2][11] = 144;
	RES[2][12] = 233;
	RES[2][13] = 377;
	RES[2][14] = 610;
	RES[2][15] = 987;
	RES[2][16] = 1597;
	RES[3][1] = 0;
	RES[3][2] = 3;
	RES[3][3] = 0;
	RES[3][4] = 11;
	RES[3][5] = 0;
	RES[3][6] = 41;
	RES[3][7] = 0;
	RES[3][8] = 153;
	RES[3][9] = 0;
	RES[3][10] = 571;
	RES[3][11] = 0;
	RES[3][12] = 2131;
	RES[3][13] = 0;
	RES[3][14] = 7953;
	RES[3][15] = 0;
	RES[3][16] = 29681;
	RES[4][1] = 1;
	RES[4][2] = 5;
	RES[4][3] = 11;
	RES[4][4] = 36;
	RES[4][5] = 95;
	RES[4][6] = 281;
	RES[4][7] = 781;
	RES[4][8] = 2245;
	RES[4][9] = 6336;
	RES[4][10] = 18061;
	RES[4][11] = 51205;
	RES[4][12] = 145601;
	RES[4][13] = 413351;
	RES[4][14] = 1174500;
	RES[4][15] = 3335651;
	RES[4][16] = 9475901;
	RES[5][1] = 0;
	RES[5][2] = 8;
	RES[5][3] = 0;
	RES[5][4] = 95;
	RES[5][5] = 0;
	RES[5][6] = 1183;
	RES[5][7] = 0;
	RES[5][8] = 14824;
	RES[5][9] = 0;
	RES[5][10] = 185921;
	RES[5][11] = 0;
	RES[5][12] = 2332097;
	RES[5][13] = 0;
	RES[5][14] = 29253160;
	RES[5][15] = 0;
	RES[5][16] = 366944287;
	RES[6][1] = 1;
	RES[6][2] = 13;
	RES[6][3] = 41;
	RES[6][4] = 281;
	RES[6][5] = 1183;
	RES[6][6] = 6728;
	RES[6][7] = 31529;
	RES[6][8] = 167089;
	RES[6][9] = 817991;
	RES[6][10] = 4213133;
	RES[6][11] = 21001799;
	RES[6][12] = 106912793;
	RES[6][13] = 536948224;
	RES[6][14] = 720246619;
	RES[6][15] = 704300462;
	RES[6][16] = 289288426;
	RES[7][1] = 0;
	RES[7][2] = 21;
	RES[7][3] = 0;
	RES[7][4] = 781;
	RES[7][5] = 0;
	RES[7][6] = 31529;
	RES[7][7] = 0;
	RES[7][8] = 1292697;
	RES[7][9] = 0;
	RES[7][10] = 53175517;
	RES[7][11] = 0;
	RES[7][12] = 188978103;
	RES[7][13] = 0;
	RES[7][14] = 124166811;
	RES[7][15] = 0;
	RES[7][16] = 708175999;
	RES[8][1] = 1;
	RES[8][2] = 34;
	RES[8][3] = 153;
	RES[8][4] = 2245;
	RES[8][5] = 14824;
	RES[8][6] = 167089;
	RES[8][7] = 1292697;
	RES[8][8] = 12988816;
	RES[8][9] = 108435745;
	RES[8][10] = 31151234;
	RES[8][11] = 940739768;
	RES[8][12] = 741005255;
	RES[8][13] = 164248716;
	RES[8][14] = 498190405;
	RES[8][15] = 200052235;
	RES[8][16] = 282756494;
	RES[9][1] = 0;
	RES[9][2] = 55;
	RES[9][3] = 0;
	RES[9][4] = 6336;
	RES[9][5] = 0;
	RES[9][6] = 817991;
	RES[9][7] = 0;
	RES[9][8] = 108435745;
	RES[9][9] = 0;
	RES[9][10] = 479521663;
	RES[9][11] = 0;
	RES[9][12] = 528655152;
	RES[9][13] = 0;
	RES[9][14] = 764896039;
	RES[9][15] = 0;
	RES[9][16] = 416579196;
	RES[10][1] = 1;
	RES[10][2] = 89;
	RES[10][3] = 571;
	RES[10][4] = 18061;
	RES[10][5] = 185921;
	RES[10][6] = 4213133;
	RES[10][7] = 53175517;
	RES[10][8] = 31151234;
	RES[10][9] = 479521663;
	RES[10][10] = 584044562;
	RES[10][11] = 472546535;
	RES[10][12] = 732130620;
	RES[10][13] = 186229290;
	RES[10][14] = 274787842;
	RES[10][15] = 732073997;
	RES[10][16] = 320338127;
	RES[11][1] = 0;
	RES[11][2] = 144;
	RES[11][3] = 0;
	RES[11][4] = 51205;
	RES[11][5] = 0;
	RES[11][6] = 21001799;
	RES[11][7] = 0;
	RES[11][8] = 940739768;
	RES[11][9] = 0;
	RES[11][10] = 472546535;
	RES[11][11] = 0;
	RES[11][12] = 177126748;
	RES[11][13] = 0;
	RES[11][14] = 513673802;
	RES[11][15] = 0;
	RES[11][16] = 881924366;
	RES[12][1] = 1;
	RES[12][2] = 233;
	RES[12][3] = 2131;
	RES[12][4] = 145601;
	RES[12][5] = 2332097;
	RES[12][6] = 106912793;
	RES[12][7] = 188978103;
	RES[12][8] = 741005255;
	RES[12][9] = 528655152;
	RES[12][10] = 732130620;
	RES[12][11] = 177126748;
	RES[12][12] = 150536661;
	RES[12][13] = 389322891;
	RES[12][14] = 371114062;
	RES[12][15] = 65334618;
	RES[12][16] = 119004311;
	RES[13][1] = 0;
	RES[13][2] = 377;
	RES[13][3] = 0;
	RES[13][4] = 413351;
	RES[13][5] = 0;
	RES[13][6] = 536948224;
	RES[13][7] = 0;
	RES[13][8] = 164248716;
	RES[13][9] = 0;
	RES[13][10] = 186229290;
	RES[13][11] = 0;
	RES[13][12] = 389322891;
	RES[13][13] = 0;
	RES[13][14] = 351258337;
	RES[13][15] = 0;
	RES[13][16] = 144590622;
	RES[14][1] = 1;
	RES[14][2] = 610;
	RES[14][3] = 7953;
	RES[14][4] = 1174500;
	RES[14][5] = 29253160;
	RES[14][6] = 720246619;
	RES[14][7] = 124166811;
	RES[14][8] = 498190405;
	RES[14][9] = 764896039;
	RES[14][10] = 274787842;
	RES[14][11] = 513673802;
	RES[14][12] = 371114062;
	RES[14][13] = 351258337;
	RES[14][14] = 722065660;
	RES[14][15] = 236847118;
	RES[14][16] = 451896972;
	RES[15][1] = 0;
	RES[15][2] = 987;
	RES[15][3] = 0;
	RES[15][4] = 3335651;
	RES[15][5] = 0;
	RES[15][6] = 704300462;
	RES[15][7] = 0;
	RES[15][8] = 200052235;
	RES[15][9] = 0;
	RES[15][10] = 732073997;
	RES[15][11] = 0;
	RES[15][12] = 65334618;
	RES[15][13] = 0;
	RES[15][14] = 236847118;
	RES[15][15] = 0;
	RES[15][16] = 974417347;
	RES[16][1] = 1;
	RES[16][2] = 1597;
	RES[16][3] = 29681;
	RES[16][4] = 9475901;
	RES[16][5] = 366944287;
	RES[16][6] = 289288426;
	RES[16][7] = 708175999;
	RES[16][8] = 282756494;
	RES[16][9] = 416579196;
	RES[16][10] = 320338127;
	RES[16][11] = 881924366;
	RES[16][12] = 119004311;
	RES[16][13] = 144590622;
	RES[16][14] = 451896972;
	RES[16][15] = 974417347;
	RES[16][16] = 378503901;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值