题解:P16256 [DSTOI Round 0] 相思若循 3
考虑序列
记
::::info[情况一]{open}
若
::::
::::info[情况二]{open}
若
- 前面压得住,后面压不住:
y_i \le X 且y_{i+1} > Y 。前i 个最大值\le X ,第i+1 个得飙到> Y 。方案数为\frac{X!}{(X-i)!} \cdot (n-Y) \cdot (n-i-1)! 。 - 前面压不住,后面压住了:
y_i > X 且y_{i+1} \le Y 。前i 个最大值在(X, Y] 之间,第i+1 个\le Y 。方案数为\frac{Y!}{(Y-i-1)!} \cdot (n-i-1)! 。
两部分相加,合并得
::::
对每个
::::success[Code]
#include <bits/stdc++.h>
using namespace std;
const long long MOD = 998244353;
long long pw(long long b, long long e, long long mod) {
long long r = 1;
while (e) {
if (e & 1) r = r * b % mod;
b = b * b % mod;
e >>= 1;
}
return r;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++) cin >> a[i];
vector<long long> fac(n + 1), ifac(n + 1);
fac[0] = 1;
for (int i = 1; i <= n; i++) fac[i] = fac[i - 1] * i % MOD;
ifac[n] = pw(fac[n], MOD - 2, MOD);
for (int i = n; i >= 1; i--) ifac[i - 1] = ifac[i] * i % MOD;
vector<int> x(n + 1);
int mx = 0;
for (int i = 1; i <= n; i++) {
if (a[i] > mx) mx = a[i];
x[i] = mx;
}
long long ans = 0;
for (int i = 1; i <= n - 1; i++) {
int X = x[i], Y = x[i + 1];
long long t;
if (X == Y) {
t = fac[X] * ifac[X - i] % MOD * (n - X) % MOD * fac[n - i - 1] % MOD;
} else {
long long c1 = (n + i - 2LL * Y) % MOD;
if (c1 < 0) c1 += MOD;
long long t1 = fac[X] * ifac[X - i] % MOD * c1 % MOD;
long long t2 = fac[Y] * ifac[Y - i - 1] % MOD;
t = fac[n - i - 1] * ((t1 + t2) % MOD) % MOD;
}
ans += t;
if (ans >= MOD) ans -= MOD;
}
cout << ans << "\n";
return 0;
}
::::