cf1606 E. Arena
题意:
有 n 个人,每个回合开始时,每个人对其他所有人造成1点伤害;回合结束时结算伤害,血量小于 1 的死亡。
每个人的初始血量 \(\in [1,x]\),现在你要为 n 个人指定初始血量,问方案数
输入只有两个数,\(2\le n \le 500,1\le x\le 500\)
思路:
没搞懂没搞懂。下面复读一下官方题解
\(f(i,j)\) 表示当前有 \(i\) 个人存活,这 \(i\) 个人每个人(至今已经)受到了 \(j\) 点伤害的方案数
初始 \(f(n,0)=1\),目标 \(ans=\sum f(0,1\sim x)\)
假设现在有 \(i\) 个人存活,进行一个回合后剩下 \(k\) 个人存活(\(k\in [0,i]\)),那么
这 \(k\) 个人(至今已经)受到的伤害为 \(d = \min \{x,j+i-1\}\)
这一回合中死掉了 \(i-k\) 个人,他们的初始血量 \(\in (j,d]\)
那我们现在就安排一下这回合死掉的人就行了(为啥为啥为啥),即
\(f(k,d) += f(i,j)\cdot C_{i}^{i-k} (d-j)^{i-k}\)
式子里的组合数和幂都可以n^2预处理
void sol() {
cin >> n >> x;
f[n][0] = 1;
for(int i = n; i; i--)
for(int j = 0; j <= x; j++)
for(int k = 0, d = min(x, j+i-1ll); k <= i; k++)
add(f[k][d], f[i][j] * C[i][k] % mod * mi[d-j][i-k] % mod);
ll ans = 0;
for(int i = 1; i <= x; i++) ans += f[0][i];
cout << ans % mod;
}

浙公网安备 33010602011771号