Description
长度为n的序列可以涂RGB三种颜色,m个限制形如l,r,x表示l到r有恰好x种颜色
问满足所有要求的涂色方案数
n
≤
300
n\le300
n≤300
Solution
一开始想到了一个非常假的做法。。结果当然没过啦
设f[i,a,b,c]表示到了第i个位置,三种颜色最后出现的位置分别是a、b、c的方案数。这个转移非常好想
然后我们可以发现每个位置都要涂色,那么就可以设f[a,b,c]这样了。对于限制我们把限制挂在r上,那么讨论一下三种颜色和l的关系就可以转移了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fi first
#define se second
typedef std:: pair <int,int> pair;
const int MOD=1e9+7;
const int N=305;
int f[N][N][N];
std:: vector <pair> vec[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void upd(int &x,int v) {
x+=v; (x>=MOD)?(x-=MOD):0;
}
int main(void) {
int n=read(),m=read();
rep(i,1,m) {
int l=read(),r=read(),x=read();
vec[r].push_back(pair(l,x));
}
f[1][0][0]=3;
rep(i,1,n-1) {
rep(j,0,i) {
rep(k,0,j) {
if (!f[i][j][k]) continue;
for (int t=0;t<vec[i].size();++t) {
int l=vec[i][t].fi,x=vec[i][t].se;
if ((x==1)&&(l<=j)) {f[i][j][k]=0; break;}
if ((x==2)&&(l<=k||l>j)) {f[i][j][k]=0; break;}
if ((x==3)&&l>k) {f[i][j][k]=0; break;}
}
if (!f[i][j][k]) continue;
upd(f[i+1][j][k],f[i][j][k]);
upd(f[i+1][i][j],f[i][j][k]);
upd(f[i+1][i][k],f[i][j][k]);
}
}
}
int ans=0;
rep(j,0,n) rep(k,0,j) {
if (!f[n][j][k]) continue;
for (int t=0;t<vec[n].size();++t) {
int l=vec[n][t].fi,x=vec[n][t].se;
if ((x==1)&&(l<=j)) {f[n][j][k]=0; break;}
if ((x==2)&&(l<=k||l>j)) {f[n][j][k]=0; break;}
if ((x==3)&&l>k) {f[n][j][k]=0; break;}
}
if (!f[n][j][k]) continue;
upd(ans,f[n][j][k]);
}
printf("%d\n", ans);
return 0;
}