Bupt归队赛, gunfight
只需要关心是否开枪,上个人和当前这个人的位置关系,转移可以前缀和优化
为了不重复,始终认为第一个就是1,最后答案乘以n
#include<bits/stdc++.h> using namespace std; #define rep(i, j, k) for (int i = int(j); i <= int(k); ++ i) #define dwn(i, j, k) for (int i = int(j); i >= int(k); -- i) typedef long long LL; const LL MOD = 1e9 + 7; const int N = 153; LL dp[2][N][N][2], pre[2][N][N][2], suf[2][N][N][2]; int main() { // 前i个人,第i个人在第j个位置,有k个活着的人,这个人的状态为t(是否开枪) LL n, k; while (cin >> n >> k) { rep(i, 0, 1) rep(j, 1, n) rep(k, 0, n) rep(t, 0, 1) dp[i][j][k][t] = suf[i][j][k][t] = pre[i][j][k][t] = 0; dp[1][1][0][0] = 1; pre[1][1][0][0] = suf[1][1][0][0] = 1; rep(i, 2, n - 1) { int cur = i & 1, last = cur ^ 1; rep(j, 1, i) rep(k, 0, i) rep(t, 0, 1) { dp[cur][j][k][t] = k >= (t == 1)? pre[last][j - 1][k - (t == 1)][1 - t]: 0; if (t == 1) { (dp[cur][j][k][t] += (k >= 1? suf[last][j][k - 1][0]: 0) + suf[last][j][k][1]) %= MOD; } } rep(k, 0, i) rep(t, 0, 1) pre[cur][0][k][t] = 0, suf[cur][i + 1][k][t] = 0; rep(j, 1, i) rep(k, 0, i) rep(t, 0, 1) (pre[cur][j][k][t] = pre[cur][j - 1][k][t] + dp[cur][j][k][t]) %= MOD; dwn(j, i, 1) rep(k, 0, i) rep(t, 0, 1) (suf[cur][j][k][t] = suf[cur][j + 1][k][t] + dp[cur][j][k][t]) %= MOD; } LL ans = 0; rep(i, 1, n - 1) { (ans += 1LL * dp[(n - 1) & 1][i][k - 1][0] + 1LL * dp[(n - 1) & 1][i][k][1]) %= MOD; } ans = ans * (LL)n % MOD; cout << ans << endl; } }