解題思路:git
首先對於覆蓋一個位置的全部限制,只須要取最小的那個便可,而後全部限制的位置都不交了,分別計算方案數相乘便可。spa
那麼問題就轉化爲若干個位置能夠放黑白兩種顏色的球,要求每個限制區間裏面必須有一個黑球,求方案數。其中一個白球有 $m_i-1$ 種方案。code
假設對第 $k$ 種限制計算,令 $dp(i,j)$ 爲前 $i$ 個位置最後一個黑球放在 $j$ 的方案數,維護一下每個位置對應的限制最左邊的黑球能夠放在哪裏,記爲 $lim[i]$ 。 $$ dp(i,j)=dp(i-1,j)\times (m_k-1)^{size_i} \ (lim[i]\leq j < i)\ dp(i,i)=\sum dp(i-1,j)\times(m_k^{sizei}-(m_k-1)^{size_i}) $$ 複雜度 $\mathcal O(Tn^2)$ 。get
/*program by mangoyang*/ #include<bits/stdc++.h> #define inf (0x7f7f7f7f) #define Max(a, b) ((a) > (b) ? (a) : (b)) #define Min(a, b) ((a) < (b) ? (a) : (b)) typedef long long ll; using namespace std; template <class T> inline void read(T &x){ int ch = 0, f = 0; x = 0; for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1; for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48; if(f) x = -x; } #define int ll const int N = 2005, mod = 998244353; inline int Pow(int a, int b){ int ans = 1; for(; b; b >>= 1, a = a * a % mod) if(b & 1) ans = ans * a % mod; return ans; } set<int> st; int n, q, A, l[N], r[N], w[N], s[N], t[N], dp[N][N], mn[N], mx[N], len, total_data; inline int calc(int now){ int tot = 0; for(int i = 1; i <= len; i++) if(mn[i] == now) t[++tot] = i; if(!tot) return -1; for(int i = 1; i <= tot; i++) mx[i] = 0; for(int i = 1; i <= q; i++) if(w[i] == now){ int L = lower_bound(t + 1, t + tot + 1, l[i]) - t; int R = lower_bound(t + 1, t + tot + 1, r[i]) - t - 1; mx[R] = max(mx[R], L); } dp[0][0] = 1; for(int i = 1; i <= tot; i++){ dp[i][i] = 0; int choose0 = Pow(now - 1, s[t[i]+1] - s[t[i]]); int choose1 = Pow(now, s[t[i]+1] - s[t[i]]); for(int j = 0; j < i; j++){ if(j >= mx[i]) dp[i][j] = dp[i-1][j] * choose0 % mod; else dp[i][j] = 0; dp[i][i] = (dp[i][i] + dp[i-1][j] * ((choose1 + mod - choose0) % mod) % mod) % mod; } } int res = 0; for(int i = 0; i <= tot; i++) res = (res + dp[tot][i]) % mod; return res; } inline void solve(){ st.clear(), read(n), read(q), read(A), s[len=1] = 1; for(int i = 1; i <= q; i++){ read(l[i]), read(r[i]), read(w[i]), r[i]++; s[++len] = l[i], s[++len] = r[i], st.insert(w[i]); } s[++len] = n + 1, sort(s + 1, s + len + 1); len = unique(s + 1, s + len + 1) - s - 1; for(int i = 1; i <= len; i++) mn[i] = A + 1; for(int i = 1; i <= q; i++){ l[i] = lower_bound(s + 1, s + len + 1, l[i]) - s; r[i] = lower_bound(s + 1, s + len + 1, r[i]) - s; for(int j = l[i]; j < r[i]; j++) mn[j] = min(mn[j], w[i]); } int res = 1, x; static set<int>::iterator it; for(it = st.begin(); it != st.end(); it++){ if(~(x = calc(*it))) res = res * x % mod; else return (void) (puts("0")); } for(int i = 1; i < len; i++) if(mn[i] == A + 1) res = res * Pow(A, s[i+1] - s[i]) % mod; printf("%lld\n", res); } signed main(){ int T; read(T); while(T--) solve(); return 0; }