Educational Codeforces Round 116 (Rated for Div. 2) E. Arena(组合数,DP )

Posted issue是fw

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Educational Codeforces Round 116 (Rated for Div. 2) E. Arena(组合数,DP )相关的知识,希望对你有一定的参考价值。

Link

考虑第一批人在第 k k k轮死掉,那么这些死掉的人血量在 [ ( k − 1 ) ∗ ( n − 1 ) + 1 , k ∗ ( n − 1 ) ] [(k-1)*(n-1)+1,k*(n-1)] [(k1)(n1)+1,k(n1)]范围内

定义 f [ i ] [ j ] f[i][j] f[i][j]表示已经死了 i i i个人,且剩下的 n − i n-i ni个人可以是 [ j + 1 , x ] [j+1,x] [j+1,x]的任何血量

转移的时候枚举下一批过了 k k k轮死掉 q q q人,那么容易推得下一批人的血量范围是

[ j + ( k − 1 ) ∗ ( n − i − 1 ) + 1 , j + k ∗ ( n − i − 1 ) ] [j+(k-1)*(n-i-1)+1,j+k*(n-i-1)] [j+(k1)(ni1)+1,j+k(ni1)]

而且,剩下的 n − ( i + q ) n-(i+q) n(i+q)人血量大于 j + k ∗ ( n − i − 1 ) j+k*(n-i-1) j+k(ni1)

转移就非常简单了,枚举下一批人过了 k k k轮死 q q q

我们先令 l = j + ( k − 1 ) ∗ ( n − i − 1 ) + 1 l=j+(k-1)*(n-i-1)+1 l=j+(k1)(ni1)+1,      r = j + k ∗ ( n − i − 1 ) \\ \\ \\ \\ r=j+k*(n-i-1)     r=j+k(ni1)

f [ i + q ] [ r ]   + = ( n − i q ) ∗ f [ i ] [ j ] ∗ ( r − l + 1 ) q f[i+q][r]\\ += \\binom{n-i}{q}*f[i][j]*(r-l+1)^q f[i+q][r] +=(qni)f[i][j](rl+1)q

意思是从剩余的 n − i n-i ni个人选出 q q q个人来死,每个人血量都应该是区间内的值有 r − l + 1 r-l+1 rl+1种取法

看上去复杂度是 O ( n 4 ) O(n^4) O(n4),实际上由于有效状态有限,循环不满,甚至比 O ( n 3 ) O(n^3) O(n3)还快

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 3e5+10;
const int mod = 998244353;
int n,x,f[509][509],fac[509],base[509][509],c[509][509];
void init()
{
    fac[0] = 1;
    for(int i=1;i<=500;i++) fac[i] = fac[i-1]*i%mod;
    for(int j=1;j<=500;j++)	base[0][j] = 1;
    for(int j=1;j<=500;j++)
	for(int i=1;i<=500;i++)
		base[i][j] = base[i-1][j]*j%mod; 
	//i个人最大血量为j时的方案(不考虑任何顺序)
	for(int i=0;i<=500;i++)
	{
		c[i][0] = 1;
        for(int j=1;j<=i;j++)
            c[i][j] = ( c[i-1][j-1]+c[i-1][j] )%mod;
	}
}
int C(int n,int m) { return c[n][m]; }
signed main()
{
    init();
	cin >> n >> x;
	f[0][0] = 1;
	for(int i=0;i<=n;i++)
    for(int j=0;j<=x;j++)
    {
        if( f[i][j]==0 )    continue;
        for(int q=1;q<=n-i-1;q++)//本次死人数目
        for(int k=1; ;k++)//过了k轮再死的
        {
            int l = j+(k-1)*(n-i-1)+1, r = j+k*(n-i-1);
            if( r>=x )  break;
            f[i+q][r] = ( f[i+q][r]+C(n-i,q)*f[i][j]%mod*base[q][r-l+1]%mod )%mod;
        }
    }
    int ans = 1, res = 0;
    for(int i=1;i<=n;i++)	ans = ans*x%mod;
    for(int i=0;i<=x;i++)   res = ( res+f[n-1][i]*(x-i)%mod )%mod;
    ans = ( ans-res )%mod;
    cout << ( ans%mod+mod )%mod;
}

以上是关于Educational Codeforces Round 116 (Rated for Div. 2) E. Arena(组合数,DP )的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 7 A

Educational Codeforces Round 7

Educational Codeforces Round 90

Educational Codeforces Round 33

Codeforces Educational Codeforces Round 54 题解

Educational Codeforces Round 27