有n行格子,第i(1<=i<=n)行有i个格子,每行格子是左对齐。现在要在每一个格子填入一个非负整数,最后使得每一行每一列的和都不超过2。
请计算有多少种方案,答案比较大,请输出对100,000,007(1e8+7)取余后的结果。
下图是n=4的时候格子的摆放。

第1行:给出一个整数n (1<=n<=200)。
对于每个测试用例,输出结果占一行。
1
3
题解:设dp[i][j][k]为到达第i行时有j列和为1,k列和为2的数量。
则第有7种状态能到达第i行。
首先每行和至多为2,首先考虑第i行全是0:
dp[i][j][k] = dp[i - 1][j][k];
其次考虑第i行往上加一个1.可以在列和为0的列加1,也可以在列和为1的列加1:
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j + 1][k - 1] * (j + 1)) % mod;
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j - 1][k] * (i - j - k + 1)) % mod;
考虑在第i行加一个2
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j][k - 1] * (i - j - k + 1)) % mod;
考虑在第i行加两个1,可以在两个列和为0的列,可以在两个列和为1的列, 可以在列和为1和列和为0的列;
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j][k - 1] * j * (i - j - k + 1)) % mod;
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j - 2][k] * (i - j - k + 2) * (i - j - k + 1) / 2) % mod;
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j + 2][k - 2] * (j + 2) * (j + 1) / 2) % mod;
最后将第n行的所有情况加起来即可(注意取模)
AC代码
#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cmath>
typedef long long ll;
using namespace std;
const ll maxn = 205, mod = 1e8 + 7;
ll dp[maxn][maxn][maxn] = {0};
int main(){
ll n;
scanf("%lld", &n);
dp[0][0][0] = 1;
for(ll i = 1; i <= n; i++)
for(ll j = 0; j <= i; j++)
for(ll k = 0; k + j <= i; k++){
dp[i][j][k] = dp[i - 1][j][k]; //第i行不放
if(j - 1 >= 0)
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j - 1][k] * (i - j - k + 1)) % mod; //第i行放一个1在列和为0的位置
if(k - 1 >= 0){
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j + 1][k - 1] * (j + 1)) % mod; //第i行放一个1在列和为1的位置
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j][k - 1] * (i - j - k + 1)) % mod; //第i行放一个2在列和为0的位置
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j][k - 1] * j * (i - j - k + 1)) % mod;//第i行放一个1在列和为1的位置,放一个1在列和为0的位置
}
if(j - 2 >= 0)
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j - 2][k] * (i - j - k + 2) * (i - j - k + 1) / 2) % mod; //第i行放两个1在列和为0的位置
if(k - 2 >= 0)
dp[i][j][k] = (dp[i][j][k] + dp[i - 1][j + 2][k - 2] * (j + 2) * (j + 1) / 2) % mod;//第i行放两个1在列和为1的位置
}
ll ans = 0;
for(ll i = 0; i <= n; i++)
for(ll j = 0; j <= n; j++)
ans = (ans + dp[n][i][j]) % mod;
printf("%lld\n", ans);
return 0;
}