题解 P4229 某位歌姬的故事
洛谷题面传送门
首先将限制写成左开右闭区间的形式并离散化,下面默认
我们考虑设
因此我们考虑对每种
到这里,问题就和远古时期做的一道题 P3600 随机数生成器 一样了,按照那题的套路,设
const int MAXN = 500;
const int MOD = 998244353;
const int INF = 0x3f3f3f3f;
int qpow(int x, int e) {
int ret = 1;
for (; e; e >>= 1, x = 1ll * x * x % MOD)
if (e & 1) ret = 1ll * ret * x % MOD;
return ret;
}
int n, m, A, key[MAXN * 2 + 5], uni[MAXN * 2 + 5], cnt, num;
struct event {int l, r, v;} q[MAXN + 5];
int mx[MAXN * 2 + 5], dp[MAXN * 2 + 5], ppw[MAXN * 2 + 5];
void clear() {
memset(key, 0, sizeof(key)); memset(uni, 0, sizeof(uni));
cnt = num = 0;
}
int calc(int val, vector<int> A, vector<int> B) {
if (A.empty()) return 0; memset(dp, 0, sizeof(dp)); dp[0] = 1;
int len = A.size(); A.insert(A.begin(), 0);
for (int i = 1; i <= len; i++) ppw[i] = qpow(val - 1, uni[A[i] + 1] - uni[A[i]]);
for (int i = 1; i <= len; i++) {
int mx = 0, pw = (qpow(val, uni[A[i] + 1] - uni[A[i]]) - qpow(val - 1, uni[A[i] + 1] - uni[A[i]]) + MOD) % MOD;
for (int id : B) if (q[id].r <= A[i]) chkmax(mx, q[id].l);
for (int j = i - 1; A[j] >= mx && j >= 0; j--) {
dp[i] = (dp[i] + 1ll * dp[j] * pw) % MOD;
pw = 1ll * pw * ppw[j] % MOD;
}
// printf("dp[%d] = %d %d\n", i, dp[i], mx);
}
int res = 0;
for (int i = 0; i <= len; i++) {
bool flg = 1;
for (int id : B) if (q[id].l > A[i]) {flg = 0; break;}
if (flg) {
int pw = 1;
for (int j = i + 1; j <= len; j++) pw = 1ll * pw * ppw[j] % MOD;
res = (res + 1ll * dp[i] * pw) % MOD;
}
}
// printf("! %d %d\n", val, res);
return res;
}
void solve() {
scanf("%d%d%d", &n, &m, &A); clear(); set<int> st;
for (int i = 1; i <= m; i++) {
scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].v);
q[i].r++; key[++cnt] = q[i].l; key[++cnt] = q[i].r;
st.insert(q[i].v);
}
sort(key + 1, key + cnt + 1);
for (int i = 1; i <= cnt; i++) if (key[i] != key[i - 1])
uni[++num] = key[i];
uni[num + 1] = n + 1;
for (int i = 1; i <= m; i++) {
q[i].l = lower_bound(uni + 1, uni + num + 1, q[i].l) - uni;
q[i].r = lower_bound(uni + 1, uni + num + 1, q[i].r) - uni;
}
memset(mx, 63, sizeof(mx));
for (int i = 1; i <= m; i++) for (int j = q[i].l; j < q[i].r; j++)
chkmin(mx[j], q[i].v);
// for (int i = 1; i <= num; i++) printf("%d%c", mx[i], " \n"[i == num]);
int sum = 0, prd;
for (int i = 1; i <= num; i++) if (mx[i] != INF)
sum += uni[i + 1] - uni[i];
prd = qpow(A, n - sum);
for (int val : st) {
vector<int> pts, eves;
for (int i = 1; i <= num; i++) if (mx[i] == val) pts.pb(i);
for (int i = 1; i <= m; i++) if (q[i].v == val) eves.pb(i);
prd = 1ll * prd * calc(val, pts, eves) % MOD;
}
printf("%d\n", prd);
}
int main() {
int qu; scanf("%d", &qu); while (qu--) solve();
return 0;
}
/*
1
7 5 7
5 7 7
4 6 7
2 4 5
3 5 5
1 3 5
*/