Description
丰泽爷今天也在愉快地玩Minecraft!
现在丰泽爷有一块1∗N的空地,每个格子按照顺序标记为1到N。丰泽爷想要在这块空地上铺上红石块、绿宝石块和钻石块作为装饰。每个格子只能选择一种方块。
丰泽爷有自己的审美标准。他定下了M条规定,每条规定形如(li,ri,xi),表示闭区间[li,ri]中,需要有恰好xi种不同的方块。
丰泽爷觉得这个任务实在是太简单了,于是把它交给了你,但是你发现有太多种方式可以满足丰泽爷的审美需求了!于是你希望先知道,一共有多少铺方块的方法,可以满足丰泽爷的审美需求?答案对109+7取模
Input
第一行两个整数,N,M
接下来M行,每行三个整数li,ri,xi
Output
一个整数,对109+7取模后的答案
Solution
比较神奇的状态设计。
设dp[i][j][k]为枚举到第i个格子,离i次远的颜色不同于i的格子为j(j<i),离i最远的颜色不同于i,j的格子为k的方案数。
那么转移就很显然了。
{
d
p
[
i
+
1
]
[
j
]
[
k
]
+
=
d
p
[
i
]
[
j
]
[
k
]
d
p
[
i
+
1
]
[
i
]
[
k
]
+
=
d
p
[
i
]
[
j
]
[
k
]
d
p
[
i
+
1
]
[
i
]
[
j
]
+
=
d
p
[
i
]
[
j
]
[
k
]
\begin{cases} dp[i+1][j][k]+=dp[i][j][k]\\ dp[i+1][i][k]+=dp[i][j][k]\\ dp[i+1][i][j]+=dp[i][j][k]\\ \end{cases}
⎩⎪⎨⎪⎧dp[i+1][j][k]+=dp[i][j][k]dp[i+1][i][k]+=dp[i][j][k]dp[i+1][i][j]+=dp[i][j][k]
第一行是i+1取跟i一样的颜色。
第二行是i+1取跟j一样的颜色。
第二行是i+1取跟k一样的颜色。
这里用了ctrl+cv
再考虑l,r的限制,对于
r
x
=
i
r_x=i
rx=i的情况,直接把不可行的情况置为0。
随便想想就知道怎么搞了。
最后乘个3,因为起始颜色不固定,或者把dp[1][0][0]直接设为3。
Code
#include<bits/stdc++.h>
#define pb push_back
#define mp make_pair
using namespace std;
const int mod=1e9+7;
int f[310][310][310],n,m;
vector< pair<int,int> >v[310];
int main(){
int l,r,x;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d",&l,&r,&x);
v[r].pb(mp(l,x));
}
f[1][0][0]=1;
for(int i=1;i<=n;i++){
for(int d=0,sz=v[i].size();d<sz;d++){
int l=v[i][d].first,x=v[i][d].second;
for(int j=0;j<i;j++)
for(int k=0;k<=max(0,j-1);k++){
if(x==1&&l<=j) f[i][j][k]=0;
if(x==2&&(l<=k||j<l)) f[i][j][k]=0;
if(x==3&&k<l) f[i][j][k]=0;
}
}
if(i==n) break;
for(int j=0;j<i;j++)
for(int k=0;k<=max(0,j-1);k++)
if(f[i][j][k]){
f[i+1][j][k]=(f[i+1][j][k]+f[i][j][k])%mod;
f[i+1][i][k]=(f[i+1][i][k]+f[i][j][k])%mod;
f[i+1][i][j]=(f[i+1][i][j]+f[i][j][k])%mod;
}
}
int ans=0;
for(int j=0;j<n;j++)
for(int k=0;k<=max(0,j-1);k++)
ans=(ans+f[n][j][k])%mod;
ans=(ans*3ll)%mod;
printf("%d",ans);
}