CF1606 E. Arena
题意:
有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); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
2020-11-10 noip2017 逛公园