P16433
::::info[闲话] 做了半场,调试出大量错误,最后和正解相差一个系数。
很多问题手推时并不能及时发现,仍需靠平时多加练习。
本题再次警示我处理细节能力的重要性,平时一定不能忽略代码实现或再依靠 AI 调试。 ::::
下面定义 关键位 表示初始有值的位,设这些位的下标分别为
思考处理顺序,贡献和真实位置相关,将值按顺序插入不可取,考虑从前到后做。
而确定前缀中每一位的具体值显然做不到,确定前缀内相对顺序则无法记录关键位上的限制。
考虑每一段内确定顺序,这样段内不会涉及到关键点的问题,段间合并由于
方便起见令
在段内设
设
考虑立即确定前两种数的具体值,第三种先记录下个数放到以后确定。
于是设
但有段内顺序就关心每个段未确定的个数,故考虑在加入时乘一些系数使得前缀内相对顺序完全确定。
枚举
直接做由于
::::info[
//#include "ascend.h"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define IL inline
const int N = 505;
int C[N][N], fac[N], mod;
int f[N][N], dp[N][N], dp1[N][N];
IL void uadd(int &x, int y) {
if ((x += y) >= mod) x -= mod;
}
int ascend(int c, int n, int __, vector<int> p, vector<int> w) {
mod = __;
for (int i = 0; i < N; ++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;
}
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
f[i][j] = 0;
fac[0] = 1;
for (int i = 1; i < N; ++i)
fac[i] = 1LL * fac[i - 1] * i % mod;
vector<int> pos, val;
pos.push_back(0); val.push_back(0);
for (int i = 0; i < n; ++i)
if (p[i]) pos.push_back(i + 1), val.push_back(p[i]);
pos.push_back(n + 1); val.push_back(n + 1);
int z = pos.size();
f[0][0] = 1;
for (int i = 0; i < z - 1; ++i) {
int L = pos[i + 1] - pos[i] - 1, S = L + 2;
int vm = val[i + 1] - val[i] - 1;
for (int l = 0; l <= S; ++l)
for (int r = 0; r <= S; ++r)
dp[l][r] = 0;
dp[1][1] = 1;
for (int j = 1; j < S; ++j) {
int _ = pos[i] - 1 + j;
int W = _ == 0 || _ == n ? 1 : w[_ - 1];
for (int l = 1; l <= j; ++l) {
for (int r = 1; r <= j; ++r) {
int t = dp[l][r], wt = 1LL * t * W % mod;
if (!t) continue;
for (int nr = 1; nr <= j + 1; ++nr)
uadd(dp1[l + (nr <= l)][nr], nr <= r ? t : wt);
}
}
for (int l = 1; l <= j + 1; ++l)
for (int r = 1; r <= j + 1; ++r)
dp[l][r] = dp1[l][r], dp1[l][r] = 0;
}
for (int j = 0; j <= pos[i]; ++j) {
int t = f[i][j];
int m = val[i] - (pos[i] - j);
if (!t || m < 0) continue;
for (int a = 0; a + 1 <= S; ++a) {
for (int b = 0; a + b + 2 <= S; ++b) {
int dpv = dp[a + 1][a + b + 2];
int coef = 1LL * C[m][a] * C[vm][b] % mod * t % mod * dpv % mod;
if (!coef) continue;
for (int x = 0; x <= j && x <= vm - b; ++x) {
int k = L - a - b, q = j - x + k;
uadd(f[i + 1][q], 1LL * coef * C[vm - b][x] % mod * C[q][k] % mod);
}
}
}
}
}
return f[z - 1][0];
}
::::
接下来对着这个东西优化:
for (int j = 0; j <= pos[i]; ++j) {
for (int a = 0; a + 1 <= S; ++a) {
for (int b = 0; a + b + 2 <= S; ++b) {
int coef = C[val[i] - pos[i] + j][a] * C[vm][b] * f[i][j] * dp[a + 1][a + b + 2];
int k = L - a - b;
for (int r = 0; r <= j; ++r)
f[i + 1][r + k] += coef * C[vm - b][j - r] * C[r + k][k];
}
}
}
首先
有
::::info[
//#include "ascend.h"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define IL inline
const int N = 505;
int C[N][N], mod;
int dp[N][N], sdp[N][N];
int g[N], f[N][N], s[N][N];
IL int add(int x, int y) { return x + y < mod ? x + y : x + y - mod; }
IL int sub(int x, int y) { return x < y ? x + mod - y : x - y; }
IL void uadd(int &x, int y) { if ((x += y) >= mod) x -= mod; }
IL int c(int n, int m) { return n < m || m < 0 ? 0 : C[n][m]; }
int ascend(int ___, int n, int __, vector<int> p, vector<int> w) {
mod = __;
for (int i = 0; i < N; ++i) {
C[i][0] = 1;
for (int j = 1; j <= i; ++j)
C[i][j] = add(C[i - 1][j - 1], C[i - 1][j]);
}
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j)
f[i][j] = 0;
vector<int> pos, val;
pos.push_back(0); val.push_back(0);
for (int i = 0; i < n; ++i)
if (p[i]) pos.push_back(i + 1), val.push_back(p[i]);
pos.push_back(n + 1); val.push_back(n + 1);
int z = pos.size();
f[0][0] = 1;
for (int i = 0; i < z - 1; ++i) {
int L = pos[i + 1] - pos[i] - 1, S = L + 2;
int vm = val[i + 1] - val[i] - 1;
for (int l = 0; l <= S; ++l)
for (int r = 0; r <= S; ++r)
dp[l][r] = sdp[l][r] = 0;
dp[1][1] = sdp[1][1] = 1;
for (int j = 2; j <= S; ++j) {
int _ = pos[i] + j - 2;
int W = _ == 0 || _ == n ? 1 : w[_ - 1];
for (int l = 1; l <= j; ++l) {
for (int r = 1, t, all; r <= j; ++r) {
if (l == r) { dp[l][r] = 0; continue; }
if (r < l) t = sdp[l - 1][r - 1], all = sdp[l - 1][j - 1];
else t = sdp[l][r - 1], all = sdp[l][j - 1];
dp[l][r] = add(1LL * t * W % mod, sub(all, t));
}
}
for (int l = 1; l <= j; ++l)
for (int r = 1; r <= j; ++r)
sdp[l][r] = add(sdp[l][r - 1], dp[l][r]);
}
for (int a = 0; a <= L; ++a) {
for (int j = 0; j <= pos[i]; ++j)
g[j] = 1LL * f[i][j] * c(val[i] - pos[i] + j, a) % mod;
for (int r = 0; r <= pos[i]; ++r)
s[0][r] = 0;
for (int r = 0; r <= pos[i]; ++r)
for (int j = r; j <= pos[i]; ++j)
uadd(s[0][r], 1LL * g[j] * c(vm, j - r) % mod);
for (int b = 1; a + b <= L; ++b)
for (int r = pos[i]; r >= 0; --r)
s[b][r] = sub(s[b - 1][r], r == pos[i] ? 0 : s[b][r + 1]);
for (int b = 0; a + b <= L; ++b) {
int k = L - a - b;
int coef = 1LL * c(vm, b) * dp[a + 1][a + b + 2] % mod;
if (!coef) continue;
for (int r = 0; r <= pos[i]; ++r)
uadd(f[i + 1][r + k], 1LL * s[b][r] * c(r + k, k) % mod * coef % mod);
}
}
}
return f[z - 1][0];
}
::::