[题目链接]
https://codeforces.com/contest/1439/problem/D
[题解]
首先解决 (N = M) 的情况。
不妨设 (dp1_{i}) 表示 (i) 个人 (i) 个座位的合法方案数 , 枚举最后一个人坐的位置。 由于左右两侧独立 , 得到
(dp1_{i}=sumlimits_{j=1}^i [j+(i-j+1)]{i-1choose j-1}dp1_{j-1}dp1_{i-j})
设 (dp2_{i}) 表示 (i) 个人 (i) 个座位 , 所有情况的移动距离之和。 枚举最后一人的座位 , 单独考虑其贡献 , 得到
(dp2_{i}=sumlimits_{j=1}^i ({jchoose 2}+{i-jchoose 2}){i-1choose j-1}dp1_{j-1}dp1_{i-j}+[j+(i-j+1)]{i-1choose j-1}(dp2_{j-1}dp1_{i-j}+dp2_{i-j}dp1_{j-1}))。
接着 , 考虑 (N > M) 的情况。
设 (dp3_{i , j}) 表示前 (i) 个人 , (j) 个座位被占用的方案数 , 枚举末尾极长一段被连续占用的座位 , 得到
(dp3_{i,j}=dp3_{i-1,j}+sumlimits_{l=1}^j {jchoose l}dp3_{i-l-1,j-l}cdot dp1_{l})
类似地 , 令 (dp_{i , j}) 表示前 (i) 个人 , (j) 个座位被占用的移动距离和 , 易知
(dp4_{i,j}=dp4_{i-1,j}+sumlimits_{l=1}^j {jchoose l}(dp4_{i-1-l,j-l}cdot dp1_{l}+dp3_{i-1-l,j-l}dp2_l))
这个做法的时间复杂度 (O(NM))。 事实上可以通过多项式做法优化至 (O(NlogN))
[代码]
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
#define rep(i , l , r) for (int i = (l); i < (r); ++i)
const int MN = 505;
int N , M , mod , dp1[MN] , dp2[MN] , dp3[MN][MN] , dp4[MN][MN] , C[MN][MN];
inline void inc(int &x , int y) {
x = x + y < mod ? x + y : x + y - mod;
}
int main() {
scanf("%d%d%d" , &N , &M , &mod);
for (int i = 0; i <= 500; ++i) {
C[i][0] = C[i][i] = 1;
for (int j = 1; j < i; ++j) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
}
dp1[0] = 1;
for (int i = 1; i <= 500; ++i) {
for (int j = 1; j <= i; ++j)
inc(dp1[i] , 1ll * dp1[j - 1] * dp1[i - j] % mod * C[i - 1][j - 1] % mod);
dp1[i] = 1ll * dp1[i] * (i + 1) % mod;
for (int j = 1; j <= i; ++j) {
inc(dp2[i] , 1ll * (i + 1) * C[i - 1][j - 1] % mod * (1LL * dp1[j - 1] * dp2[i - j] % mod + 1LL * dp2[j - 1] * dp1[i - j] % mod) % mod);
inc(dp2[i] , 1ll * C[i - 1][j - 1] * dp1[j - 1] % mod * dp1[i - j] % mod * (j * (j - 1) / 2 + (i - j) * (i - j + 1) / 2) % mod);
}
}
dp3[0][0] = 1;
for (int n = 1; n <= 500; ++n) {
for (int m = 0; m < n; ++m) {
dp3[n][m] = dp3[n - 1][m];
dp4[n][m] = dp4[n - 1][m];
for (int i = 1; i <= m; ++i) {
inc(dp3[n][m] , 1ll * dp3[n - i - 1][m - i] * dp1[i] % mod * C[m][i] % mod);
inc(dp4[n][m] , 1ll * dp3[n - i - 1][m - i] * dp2[i] % mod * C[m][i] % mod);
inc(dp4[n][m] , 1ll * dp4[n - i - 1][m - i] * dp1[i] % mod * C[m][i] % mod);
}
}
dp3[n][n] = dp1[n] , dp4[n][n] = dp2[n];
}
printf("%d
" , dp4[N][M]);
return 0;
}