Educational Codeforces Round 51 (Rated for Div. 2) -D Bicolorings

Codeforces传送门
洛谷传送门

题目描述

You are given a grid, consisting of 2 2 2 rows and n n n columns. Each cell of this grid should be colored either black or white.

Two cells are considered neighbours if they have a common border and share the same color. Two cells A A A and B B B belong to the same component if they are neighbours, or if there is a neighbour of A A A that belongs to the same component with B B B .

Let’s call some bicoloring beautiful if it has exactly k k k components.

Count the number of beautiful bicolorings. The number can be big enough, so print the answer modulo 998244353 998244353 998244353 .

输入输出格式

输入格式:

The only line contains two integers n n n and k k k ( 1 ≤ n ≤ 1000 1 \le n \le 1000 1n1000 , 1 ≤ k ≤ 2 n 1 \le k \le 2n 1k2n ) — the number of columns in a grid and the number of components required.

输出格式:

Print a single integer — the number of beautiful bicolorings modulo $998244353 $.

输入输出样例

输入样例#1:
3 4
输出样例#1:
12
输入样例#2:
4 1
输出样例#2:
2
输入样例#3:
1 2
输出样例#3:
2

说明

One of possible bicolorings in sample 1 1 1 :

img

解题分析

一开始想的是轮廓线 d p dp dp, 然后发现状态有点多, 然后发现好像暴力两行一起转移就可以了。

显然如果上一行的状态共有4种情况:黑黑,黑白,白白,白黑, 那么转移就是 O ( 4 ∗ 4 ) O(4*4) O(44)的, 总复杂度 O ( 16 ∗ N ) O(16*N) O(16N)

代码如下:

#include <cstdio>
#include <cmath>
#include <cctype>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 1050
#define MOD 998244353ll
#define ll long long
int dp[2][2][MX][MX * 2];
int n, k;
IN void mod(int &x, R int y) {x += y; if(x >= MOD) x -= MOD;}
int main(void)
{
	scanf("%d%d", &n, &k);
	dp[0][0][1][1] = 1;
	dp[1][1][1][1] = 1;
	dp[0][1][1][2] = 1;
	dp[1][0][1][2] = 1;
	for (R int i = 2; i <= n; ++i)
	{
		int bd = i * 2, pre = i - 1;
		for (R int j = 1; j <= bd; ++j)
		{
			mod(dp[0][0][i][j + 1], dp[1][1][pre][j]);
			mod(dp[0][0][i][j], dp[0][1][pre][j]);
			mod(dp[0][0][i][j], dp[1][0][pre][j]);
			mod(dp[0][0][i][j], dp[0][0][pre][j]);
			mod(dp[1][1][i][j + 1], dp[0][0][pre][j]);
			mod(dp[1][1][i][j], dp[0][1][pre][j]);
			mod(dp[1][1][i][j], dp[1][0][pre][j]);
			mod(dp[1][1][i][j], dp[1][1][pre][j]);
			mod(dp[0][1][i][j + 2], dp[1][0][pre][j]);
			mod(dp[0][1][i][j + 1], dp[1][1][pre][j]);
			mod(dp[0][1][i][j + 1], dp[0][0][pre][j]);
			mod(dp[0][1][i][j], dp[0][1][pre][j]);
			mod(dp[1][0][i][j + 2], dp[0][1][pre][j]);
			mod(dp[1][0][i][j + 1], dp[1][1][pre][j]);
			mod(dp[1][0][i][j + 1], dp[0][0][pre][j]);
			mod(dp[1][0][i][j], dp[1][0][pre][j]);
		}
	}
	int ans = 0;
	mod(ans, dp[1][1][n][k]), mod(ans, dp[0][0][n][k]), mod(ans, dp[0][1][n][k]), mod(ans, dp[1][0][n][k]);
	printf("%d", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值