CF1606 E. Arena

Problem - 1606E - Codeforces

 

题意:

有n个英雄,每一轮每个英雄向除自己之外的所有英雄发动一次攻击

每个英雄有初始血量,当承受攻击次数>=初始血量时,英雄死亡

如果最后存在一个英雄活到了最后,他就获胜

英雄初始血量上限为x

问有多少种英雄初始血量方案数,满足最后没有获胜的英雄

 

dp[i][j]表示现在还有i个英雄,活着的每个英雄已经承受j次攻击,在此情况下已经死亡英雄的初始血量方案数

设在这一轮攻击之后还剩下k个英雄活着

那么死亡了i-k个英雄

在这一轮死亡的英雄的血量至少为j+1,因为他活到了这一轮

至多为min(x,j+i-1),因为这一轮他承受了i-1次攻击,在这i-1次攻击里他死了,x时初始血量上限

所以如果一个英雄死在了这一轮,它的初始血量有min(x,j+i-1)- j 种可能

从i个英雄里选出i-k个死亡,有C(i,i-k)种选法

令nj=j+i-1

所以转移为dp[k][nj]+=dp[i][j]*C(i,i-k)*(nj-j)^(i-k)

 

 

#include<bits/stdc++.h>

using namespace std;

const int mod=998244353;

#define N 505

int dp[N][N],C[N][N];

int main()
{
    int n,x;
    scanf("%d%d",&n,&x);
    for(int i=0;i<=n;++i) C[i][0]=1;
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    dp[n][0]=1;
    int nj,pw;
    for(int i=n;i>1;--i)
        for(int j=0;j<x;++j)
        {
            nj=min(j+i-1,x);
            pw=1;
            for(int k=i;k>=0;--k,pw=1ll*pw*(nj-j)%mod)
                dp[k][nj]=(dp[k][nj]+1ll*dp[i][j]*C[i][i-k]%mod*pw%mod)%mod;
        }
    int ans=0;
    for(int i=1;i<=x;++i) ans=(ans+dp[0][i])%mod;
    printf("%d",ans);     
}

 

posted @ 2021-11-10 19:07  TRTTG  阅读(123)  评论(0编辑  收藏  举报