【XSY3209】RGB Sequence

时间:2022-12-13 04:15:44

题目

传送门

解法

用\(f_{i, j, k}\)表示有\(i\)个红石块, \(j\)个绿宝石块, \(k\)个钻石块

可以转移到\(f_{p+1, j, k}\)、 \(f_{i, p+1,k }\)、\(f_{i, j, p+1}\), \(p\)为\(max(i, j, k)\)

代码

#pragma GCC optimize(3)
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <algorithm> using namespace std; const int mod = 1000000007; const int N = 310; const int M = 310; struct node
{ int a, b;
node() { }
node(int _1, int _2) : a(_1), b(_2) { }
} list[M]; int head[N], nxt[M], tot; inline void init()
{ memset(head, -1, sizeof(head));
tot = 0;
} inline void link(int x, int y, int z)
{ list[tot] = node(y, z);
nxt[tot] = head[x];
head[x] = tot++;
} inline int max(int x, int y) { return x > y ? x : y; } inline int Plus(int a, int b) { return a + b >= mod ? a + b - mod : a + b; } int n, m; inline bool check(int a, int b, int c)
{ int num = max(a, max(b, c));
for (register int i = head[num]; ~i; i = nxt[i])
{ int l = list[i].a;
int cnt = (l <= a) + (l <= b) + (l <= c);
if (cnt != list[i].b) return 0;
}
return 1;
} int f[N][N][N]; int Dp()
{ f[0][0][0] = 1;
int Ans = 0;
register int i, j, k;
for (i = 0; i <= n; i++)
{ for (j = 0; j <= n; j++)
{ for (k = 0; k <= n; k++)
{ if (!f[i][j][k]) continue;
if (!check(i, j, k)) { f[i][j][k] = 0; continue; }
int p = max(i, max(j, k));
// if (p == n) { Ans = Plus(Ans, f[i][j][k]); continue; }
f[p+1][j][k] = Plus(f[p+1][j][k], f[i][j][k]);
f[i][p+1][k] = Plus(f[i][p+1][k], f[i][j][k]);
f[i][j][p+1] = Plus(f[i][j][p+1], f[i][j][k]);
}
}
}
for (int i = 0; i <= n; i++)
for (int j = 0; j <= n; j++)
{ Ans = Plus(Ans, f[i][j][n]);
Ans = Plus(Ans, f[i][n][j]);
Ans = Plus(Ans, f[n][i][j]);
}
return Ans;
} int main()
{ scanf("%d %d", &n, &m);
init();
for (int i = 1; i <= m; i++)
{ int l, r, x;
scanf("%d %d %d", &l, &r, &x);
if (r-l+1 < x) return 0 & puts("0");
link(r, l, x);
}
printf("%d\n", Dp());
return 0;
}