I_Love_Galgame
2024-11-18 15:14:35
我们先来证一个重要的结论:每个连通块的节点的编号一定是连续的。
要证明这个结论,我们需要说明若
我们设有
具体而言,先预处理出前缀最小值
然后,我们枚举当前位置
当
但是若干点是多少个点呢?不知道。所以就只能枚举,这样复杂度就达到了
怎么转移呢?显然有
#include<bits/stdc++.h>
using namespace std;
#define SF scanf
#define PF printf
#define int long long
const int mod = 998244353;
int qkpow(int a, int b) {
int ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
int a[2005], pre[2005], suf[2005], Min[2005], Max[2005], dp[2005][2005], Suf[2005][2005];
signed main() {
int n, m;
SF("%lld%lld", &n, &m);
for(int i = 1; i <= m; i++) dp[1][i] = 1, Suf[1][i] = m - i + 1;
for(int i = 2; i <= n; i++) {
for(int j = m; j; j--) {
dp[i][j] = (dp[i - 1][j] * (m - j + 1) % mod + Suf[i - 1][j + 1]) % mod;
Suf[i][j] = (Suf[i][j + 1] + dp[i][j]) % mod;
}
}
Min[0] = m, Max[n + 1] = 1;
for(int i = 1; i <= n; i++) SF("%lld", &a[i]), pre[i] = pre[i - 1] + (a[i] == -1), Min[i] = min(Min[i - 1], a[i] == -1 ? m : a[i]);
for(int i = n; i; i--) suf[i] = suf[i + 1] + (a[i] == -1), Max[i] = max(Max[i + 1], a[i]);
int ans = 0;
for(int i = 1; i < n; i++) {
for(int j = Min[i]; j > Max[i + 1]; j--) {
if(j == Min[i]) ans = (ans + qkpow(j - 1, suf[i + 1]) * qkpow(m - j + 1, pre[i]) % mod) % mod;
else ans = (ans + qkpow(j - 1, suf[i + 1]) * dp[pre[i]][j] % mod) % mod;
}
}
PF("%lld", (ans + qkpow(m, pre[n])) % mod);
return 0;
}