题解:
- 将原问题转换为 对于全部 (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 有四种变化的可能
- j-1 → j : 新来的情侣“一起”插入到不打断先前情侣的“相邻”座位处 dp[i+1][j] += 2 * dp[i][j-1] * (2*i+1-(j-1))
- 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)
- j+1 → j : 新来的情侣,一个插入到打断先前某对情侣的座位处,另一个插入到不打断先前情侣的座位处 dp[i+1][j] += 2 * dp[i][j+1] * (j+1)*(2*i+1-(j+1)
- 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\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); } }
原文地址:https://www.cnblogs.com/Just--Do--It/p/9460904.html
时间: 2024-10-14 06:10:15