hdu 6377 : 度度熊看球賽

題目連接php

題解:c++

  • 將原問題轉換爲 對於所有 (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

 

代碼以下spa

#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\n",2*d%mod);
            continue;
        }
        for(int i=0;i<=n;i++) ret=(ret+dp[n][i]*qpow(d,i)%mod)%mod;
        printf("%lld\n",ret);
    }
}
相關文章
相關標籤/搜索