1606E Arena

求有胜利的情况:

定义dp[i][j],i个人,生命在j内,最后剩1个人的情况

每次每个人损失i-1点生命值,枚举死亡人数k,这些人生命值小于i

dp[i][j] += dp[i-k][j-(i-1)]*(i-1)k*Cik

死亡人数有 k 个,我们要从i个人中选出 k 个人来死亡

死亡的人中,因为收到的是 i - 1 点伤害,所以他们每个人只要少于这个值都可以,总共是有 k 个人

#include <bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define dec(i,a,b) for(ll i=(a);i>=(b);i--)
#define pll pair<ll,ll>
using namespace std;
ll INF = 0x7f7f7f7f7f7f7f7f;
const int N = 5e2 + 5;
ll mod = 998244353;

ll dp[N][N];//i个人,生命值在j内,最后剩1个人的方案数
ll C[N][N];
ll qpow(ll x, ll n) {
    ll t = x, ans = 1;
    while (n) {
        if (n & 1) {
            ans = ans * t % mod;
        }
        t = t * t % mod;
        n >>= 1;
    }
    return ans;
}
int main() {
#ifdef _DEBUG
    freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    ll n, x;
    cin >> n >> x;
    C[0][0] = 1;
    rep(i, 1, N-1) {
        C[i][0] = C[i][i] = 1;
        rep(j, 1, i) {
            C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
        }
    }
    rep(i, 1, x) {
        dp[1][i] = i;
    }
    rep(i, 2, n) {// i个人
        rep(j, i, x) {// 最多j生命值
            rep(k, 0, i - 1) {// 死掉k个人
                dp[i][j] += (dp[i - k][j - (i - 1)] * qpow(i - 1, k) % mod) * C[i][k] % mod;
                dp[i][j] %= mod;
            }
        }
    }
    cout << (qpow(x, n) - dp[n][x] + mod) % mod << '\n';
    return 0;
}
原文地址:https://www.cnblogs.com/dealer/p/15798426.html