题目
Problem Description
There are N blanks arranged in a row. The blanks are numbered 1,2,…,N from left to right.
Tom is filling each blank with one number in {0,1,2,3}. According to his thought, the following M conditions must all be satisfied. The ith condition is:
There are exactly xi different numbers among blanks ∈[li,ri].
In how many ways can the blanks be filled to satisfy all the conditions? Find the answer modulo 998244353.
Input
The first line of the input contains an integer T(1≤T≤15), denoting the number of test cases.
In each test case, there are two integers n(1≤n≤100) and m(0≤m≤100) in the first line, denoting the number of blanks and the number of conditions.
For the following m lines, each line contains three integers l,r and x, denoting a condition(1≤l≤r≤n, 1≤x≤4).
Output
For each testcase, output a single line containing an integer, denoting the number of ways to paint the blanks satisfying all the conditions modulo 998244353.
Sample Input
2
1 0
4 1
1 3 3
Sample Output
4
96
Source
2019 Multi-University Training Contest 1
思路
我们想到
d
p
[
i
]
[
j
]
[
k
]
[
l
]
dp[i][j][k][l]
dp[i][j][k][l] 代表填完前
t
t
t 个位置后,
{
0
,
1
,
2
,
3
}
\left \{ 0, 1, 2, 3 \right \}
{0,1,2,3}这
4
4
4 个数字最后一次出现的位置,排序后按照第
t
+
1
t+1
t+1 位,可以得到四种转移。
滚动掉一维,空间复杂度
O
(
n
3
)
O(n^{3})
O(n3)
for循环4层,但是有顺序限制。时间复杂度差不多是
O
(
n
4
÷
24
)
O(n^{4}\div 24 )
O(n4÷24)。
很能接受
代码↓↓↓
代码
#include <bits/stdc++.h>
using namespace std;
const int M = 100 + 5;
int n, m, ans, dp[2][M][M][M];
vector <pair <int, int> > a[M];
const int mod = 998244353;
void sol(int &x) {
if (x >= mod) x -= mod;
(x >= mod) ? x -= mod : x;
}
int main() {
int T, ans = 0, l, r, x;
scanf("%d", &T);
while (T--) {
ans = 0;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) a[i].clear();
for (int i = 0; i < m; i++)
scanf("%d%d%d", &l, &r, &x), a[r].push_back(pair <int, int>(l, x));
dp[0][0][0][0] = 1;
for (int i = 1, p = 1; i <= n; i++, p ^= 1) {
for (int j = 0; j <= i; j++)
for (int k = 0; k <= j; k++)
for (int l = 0; l <= k; l++)
dp[p][j][k][l] = 0;
for (int j = 0; j < i; j++)
for (int k = 0; k <= j; k++)
for (int l = 0; l <= k; l++) {
sol(dp[p][j][k][l] += dp[p^1][j][k][l]);
sol(dp[p][i-1][k][l] += dp[p^1][j][k][l]);
sol(dp[p][i-1][j][l] += dp[p^1][j][k][l]);
sol(dp[p][i-1][j][k] += dp[p^1][j][k][l]);
}
for (int j = 0; j < i; j++)
for (int k = 0; k <= j; k++)
for (int l = 0; l <= k; l++)
for (pair <int, int> t : a[i])
if (1 + (j >= t.first) + (k >= t.first) + (l >= t.first) != t.second)
dp[p][j][k][l] = 0;
}
for (int i = 0, p = n & 1; i < n; i++)
for (int j = 0; j <= i; j++)
for (int k = 0; k <= j; k++) sol(ans += dp[p][i][j][k]);
printf("%d\n", ans);
}
return 0;
}