hdu 6377 : 度度熊看球赛

题目链接

题解:

  • 将原问题转换为 对于全部 (2n)! 种情况,每种情况对ans的贡献为 D^k,其中k表示该情况下有k对情侣座位相邻。
  • 预处理好共有 i (1<=i<=N)对情侣时,出现 j (0<=j<=i) 对情侣坐在一起时情况数,用dp[i][j]记录
  • 初始条件为dp[1][1]=2
  • 当总情侣对数由 i 向 i+1 转移时,j 有四种变化的可能
  1. j-1 → j : 新来的情侣“一起”插入到不打断先前情侣的“相邻”座位处 dp[i+1][j] += 2 * dp[i][j-1] * (2*i+1-(j-1))
  2. j → j : 新来的情侣“一起”插入到打断先前某对情侣的“相邻”座位处 dp[i+1][j] += 2 * dp[i][j] * j ,或者“分开”插入到不打断先前情侣的“不相邻”座位处  dp[i+1][j] += 2 * dp[i][j] * C(2*i+1-j,2)
  3. j+1 → j : 新来的情侣,一个插入到打断先前某对情侣的座位处,另一个插入到不打断先前情侣的座位处 dp[i+1][j] += 2 * dp[i][j+1] * (j+1)*(2*i+1-(j+1)
  4. j+2 → j : 新来的情侣“分开”插入到打断先前某两对情侣的“相邻”座位处 dp[i+1][j] += 2 * dp[i][j+2] * C(j+2,2)
  • 以上为预处理过程
  • 最后 ans += d^i * dp[n][i] ,i=0→n

代码如下

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const LL mod=998244353;

LL qpow(LL x,LL n)        //求x^n%mod
{
    LL ret=1;
    for(; n; n>>=1)
    {
        if(n&1) ret=ret*x%mod;
        x=x*x%mod;
    }
    return ret;
}

int C(LL a,LL b=2)
{
    return a*(a-1)%mod*qpow(b,mod-2)%mod;
}

const int N=1e3+5;
LL dp[N][N];

void init()
{
    dp[1][1]=2;
    for(int i=1;i<N;i++)
    {
        dp[i+1][0]=2*dp[i][0]%mod*C(2*i+1,2)%mod+
                   2*dp[i][1]%mod*2*i%mod+
                   2*dp[i][2]%mod;
        dp[i+1][0]%=mod;
        for(int j=1;j<=i+1;j++)
        {
            dp[i+1][j]=2*dp[i][j-1]%mod*(2*i+1-(j-1))%mod+
                       2*dp[i][j]%mod*(j+C(2*i+1-j,2))%mod+
                       2*dp[i][j+1]%mod*((j+1)*(2*i+1-(j+1))%mod)%mod+
                       2*dp[i][j+2]%mod*C(j+2,2)%mod;
            dp[i+1][j]%=mod;
        }
    }
}

int main()
{
    init();
    LL n,d;
    while(~scanf("%lld%lld",&n,&d))
    {
        LL ret=0;
        if(n==1)
        {
            printf("%lld
",2*d%mod);
            continue;
        }
        for(int i=0;i<=n;i++) ret=(ret+dp[n][i]*qpow(d,i)%mod)%mod;
        printf("%lld
",ret);
    }
}
原文地址:https://www.cnblogs.com/Just--Do--It/p/9460904.html