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; }