Educational Codeforces Round 116 (Rated for Div. 2) E - Arena (dp计数)
代码+分析:
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 998244353;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
int n;
int x;
ll dp[505][505];
ll f[N],invf[N];
ll fpow(ll a,ll k){
ll res=1;
while(k){
if(k&1) res=(res*a)%mod;
k>>=1;
a=a*a%mod;
//cout<<1<<endl;
}
return res;
}
void init(int n){
f[0]=1;
for(int i=1;i<=n;++i){
f[i]=f[i-1]*i%mod;
}
invf[n]=fpow(f[n],mod-2);
for(int i=n-1;i>=0;--i){
invf[i]=invf[i+1]*(i+1)%mod;
}
}
ll C(int n,int k){
if(k<0 || k>n) return 0;
return f[n]*invf[k]%mod*invf[n-k]%mod;
}
//dp[i][j]表示有i个heros并且hp不大于j
//1.如果i-1>=j,一回合后all died,贡献为j^i
//2.如果i-1<j,那我们枚举一回合后还存活了k个人,
// 那么剩余的i-k个人每个人的生命值都是不大于(i-1)的,有(i-1)^{i-k}种方案
// 再看存活的k个人,首先有C(i,k)种选择方案,再看他们死的方案数dp[k][j-(i-1)]
// 最后得到:dp[i][j]+=c(i,k)*dp[k][j-(i+1)]*(i-1)^{i-k}
int main() {
scanf("%d %d",&n,&x);
init(1000000);
for(int i=2;i<=n;++i){
for(int j=1;j<=x;++j){
if(i-1>=j){
dp[i][j]=fpow(j,i)%mod;
continue;
}
for(int k=2;k<=i;++k){
dp[i][j]=(dp[i][j]+C(i,k)*dp[k][j-(i-1)]%mod*fpow(i-1,i-k))%mod;
}
dp[i][j]=(dp[i][j]+fpow(i-1,i))%mod; //k=0的情况单独写一下
}
}
printf("%lld\n",dp[n][x]);
return 0;
}
𝓐𝓬𝓱𝓲𝓮𝓿𝓮𝓶𝓮𝓷𝓽 𝓹𝓻𝓸𝓿𝓲𝓭𝓮𝓼 𝓽𝓱𝓮 𝓸𝓷𝓵𝔂 𝓻𝓮𝓪𝓵
𝓹𝓵𝓮𝓪𝓼𝓾𝓻𝓮 𝓲𝓷 𝓵𝓲𝓯𝓮