专栏文章

题解:AT_joisc2018_c テント (Tents)

AT_joisc2018_c题解参与者 2已保存评论 1

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
1 条
当前快照
1 份
快照标识符
@minocx8e
此快照首次捕获于
2025/12/02 05:42
3 个月前
此快照最后确认于
2025/12/02 05:42
3 个月前
查看原文
水个题解。
简单 DP。考虑从上到下填帐篷,定义 dpi,jdp_{i,j} 为若当前矩阵还剩下 ii 行没填,jj 列没填,其他行和列固定的方案数。初始化 dpn,m=1dp_{n,m}=1,其余未计算,答案为 i=0m1dp0,i\sum\limits_{i=0}^{m-1}dp_{0,i}
可以跳过一行,从 dpi+1,jdp_{i+1,j} 转移来,系数是 11
可以在这一行放两个配对帐篷,从 dpi+1,j+2dp_{i+1,j+2} 转移来,系数是 (j+22)\binom{j+2}2
可以在这一行放一个自由帐篷,从 dpi+1,j+1dp_{i+1,j+1} 转移来,系数是 4×j4\times j
可以放一个帐篷然后在下面的行再选一个配对,从 dpi+2,j+1dp_{i+2,j+1} 转移来,想象我们“抽走”最上面的一行和下面的任选一行,然后再选一个列,因此系数是 (i+1)×(j+1)(i+1)\times(j+1)
如果上面的东西没想清楚,可能需要花多一些的时间调试,出题人很没素质,给点样例不是太弱就是太大,如果调不出来建议复制题解自己随便手敲一些数对比题解输出和自己的输出。
最终代码并不长。
CPP
#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
int n, m;
unsigned long long dp[3005][3005], ans;
signed main() {
	cin >> n >> m;
	for (int i = 0; i <= n; i++) {
		dp[i][m] = 1;
	}
	for (int i = n - 1; i >= 0; i--) {
		for (int j = m - 1; j >= 0; j--) {
			dp[i][j] += dp[i + 1][j];
			dp[i][j] += dp[i + 1][j + 2] * ((j + 2) * (j + 1) >> 1);
			dp[i][j] += dp[i + 1][j + 1] * ((j + 1) << 2);
			dp[i][j] += dp[i + 2][j + 1] * ((i + 1) * (j + 1));
			dp[i][j] %= mod;
		}
	}
	for (int i = 0; i < m; i++) {
		ans += dp[0][i];
	}
	cout << ans % 1000000007;
	return 0;
}

评论

1 条评论,欢迎与作者交流。

正在加载评论...