炮
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 464 Solved: 243
[Submit][Status][Discuss]
Description
众所周知,双炮叠叠将是中国象棋中很厉害的一招必杀技。炮吃子时必须隔一个棋子跳吃,即俗称"炮打隔子"。
炮跟炮显然不能在一起打起来,于是rly一天借来了许多许多的炮在棋盘上摆了起来……他想知道,在N×M的矩形
方格中摆若干炮(可以不摆)使其互不吃到的情况下方案数有几种。
棋子都是相同的。
Input
一行,两个正整数N和M。
N<=100,M<=100
Output
一行,输出方案数mod 999983。
Sample Input
1 3
Sample Output
7
HINT
Source
1 //2017-08-03 2 #include <cstdio> 3 #include <iostream> 4 #include <cstring> 5 #include <algorithm> 6 7 const int N = 110; 8 const int MOD = 999983; 9 int n, m; 10 long long dp[N][N][N];//dp[i][j][k]表示处理到第i行,一列上有0个炮的列数j,一列上有1个炮的列数k的方案数。 11 12 inline long long cal(int a, int b) 13 { 14 return b == 1 ? a : (1LL * a * (a - 1) / 2) % MOD; 15 } 16 17 int main() 18 { 19 while (scanf("%d%d", &n, &m)!=EOF) 20 { 21 memset(dp, 0, sizeof(dp)); 22 long long ans = 0; 23 dp[0][m][0] = 1; 24 for (int i = 0; i < n; ++i) 25 for (int j = 0; j <= m; ++j) 26 for (int k = 0; k <= m; ++k) 27 if (dp[i][j][k]) 28 { 29 (dp[i + 1][j][k] += dp[i][j][k]) %= MOD; 30 if (j > 0) 31 (dp[i + 1][j - 1][k + 1] += dp[i][j][k] * cal(j, 1)) %= MOD; 32 if (j > 1) 33 (dp[i + 1][j - 2][k + 2] += dp[i][j][k] * cal(j, 2)) %= MOD; 34 if (j > 0) 35 (dp[i + 1][j - 1][k] += dp[i][j][k] * cal(j, 1) % MOD * cal(k, 1)) %= MOD; 36 if (k > 0) 37 (dp[i + 1][j][k - 1] += dp[i][j][k] * cal(k, 1)) %= MOD; 38 if (k > 1) 39 (dp[i + 1][j][k - 2] += dp[i][j][k] * cal(k, 2)) %= MOD; 40 } 41 for (int i = 0; i <= m; ++i) 42 for (int j = 0; j <= m; ++j) 43 ans = (ans + dp[n][i][j]) % MOD; 44 printf("%lld ", ans); 45 } 46 }