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;
    }
}
原文地址:https://www.cnblogs.com/tempestT/p/10660897.html