好题,记录一下。
首先若干个区间限制,根据套路,我们只在右端点统计信息。
因为只有三种颜色,再看数据范围,可以考虑三维 dp。
设 \(f_{i,j,k}\) 设前 \(i\) 个数,与 \(i\) 颜色不同的两种颜色的最后出现位置 \(j,k\),规定 \(j\ge k\)(\(j=k\) 当且仅当它们都没出现,此时 \(j=k=0\))。
然后我们可以很方便的判断该状态是否合法,若合法则刷表法更新信息。
为什么用刷表法?这样做的好处是我们的 \([l,i]\) 区间全部满足条件了,对于 \(i+1\) 颜色的选择就与现在无关。
转移方程比较显然,分 \(i+1\) 填三种颜色三种情况考虑。
最后答案记得 \(\times 3\),因为我们统计时只关心颜色的相同和不同,没有关心具体颜色。
#include<bits/stdc++.h>
using namespace std;
#define rd read()
#define PII pair<int,int>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define ll long long
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define ROF(i,j,k) for(int i=j;i>=k;i--)
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)) x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
const int N=310,mod=1e9+7;
int MOD(int x){return x>=mod?x-mod:x;}
int n,m,f[N][N][N];
vector<PII> v[N];
int main(){
n=rd,m=rd;FOR(i,1,m){int l=rd,r=rd,x=rd;v[r].pb(mp(l,x));}
f[1][0][0]=1;
FOR(i,1,n){
for(auto t:v[i]){
int l=t.fi,x=t.se;
FOR(j,0,i-1){
FOR(k,0,max(0,j-1)){
if(x==1){if(l<=j) f[i][j][k]=0;}
else if(x==2){if(j<l||l<=k) f[i][j][k]=0;}
else if(x==3){if(k<l) f[i][j][k]=0;}
}
}
}
if(i==n) break;
FOR(j,0,i-1) FOR(k,0,max(0,j-1)){
if(!f[i][j][k]) continue;
f[i+1][j][k]=MOD(f[i+1][j][k]+f[i][j][k]);
f[i+1][i][k]=MOD(f[i+1][i][k]+f[i][j][k]);
f[i+1][i][j]=MOD(f[i+1][i][j]+f[i][j][k]);
}
}
int ans=0;
FOR(j,0,n) FOR(k,0,max(0,j-1)) ans=MOD(ans+f[n][j][k]);
ans=3ll*ans%mod;
printf("%d\n",ans);
return 0;
}
标签:ch,颜色,Sequence,int,rd,ARC074E,RGB,define
From: https://www.cnblogs.com/summ1t/p/18530853