题意
题解
首先很容易想到,一开始可以把剩余使用次数相同的颜色归到一类考虑。
进一步思考,就可以根据这个想法来设计
DP
状态。
我们需要记一下现在剩余使用次数为1~5的颜色各有几种。转移的时候乘一个系数即可。
有关相邻颜色不同的限制,我们可以记一个上次涂的那种颜色现在的剩余使用次数,转移到那种次数的类时把系数减1即可。
很完美的合并了状态,使复杂度可以接受。
用记忆化dfs可以省去不合法状态,就能跑的很快了。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MOD=1000000007;
int n,fst[6],f[5][16][16][16][16][16]; // 上次放的颜色现在还剩多少个, 剩 1,2,3,4,5 个的颜色分别有几个
int get(int last,int t1,int t2,int t3,int t4,int t5){
if(f[last][t1][t2][t3][t4][t5]!=-1) return f[last][t1][t2][t3][t4][t5];
if(!(t1||t2||t3||t4||t5)) return 1;
int res=0;
if(t1) (res+=(LL)get(0,t1-1,t2,t3,t4,t5)*(t1-(last==1))%MOD)%=MOD;
if(t2) (res+=(LL)get(1,t1+1,t2-1,t3,t4,t5)*(t2-(last==2))%MOD)%=MOD;
if(t3) (res+=(LL)get(2,t1,t2+1,t3-1,t4,t5)*(t3-(last==3))%MOD)%=MOD;
if(t4) (res+=(LL)get(3,t1,t2,t3+1,t4-1,t5)*(t4-(last==4))%MOD)%=MOD;
if(t5) (res+=(LL)get(4,t1,t2,t3,t4+1,t5-1)*(t5-(last==5))%MOD)%=MOD;
return f[last][t1][t2][t3][t4][t5]=res;
}
int main(){
freopen("bzoj1079.in","r",stdin);
freopen("bzoj1079.out","w",stdout);
int t; scanf("%d",&t);
while(t--){
int x; scanf("%d",&x);
n+=x; fst[x]++;
}
memset(f,255,sizeof(f));
printf("%d\n",get(0,fst[1],fst[2],fst[3],fst[4],fst[5]));
return 0;
}