~By Bartholomew~
首先我們會發現,最難的莫過於對於 dp[i] (i 表示位置) 的轉移,
當然我們會不知道對於某一些非法狀態的轉移的判斷,所以我發現自己 G_G 了!
那麼我們如果對於這一題 , 發現 k 和 c[i] 的數值都十分的小! 於是我們來找方案瞭解決它,因爲我們可以暴力開 5 維來記錄變化
dp[a][b][c][d][e][last]
表示某顏色只能塗一下的有 a 個,能塗2下的顏色b個,…3個…c個…還有就是上一次的塗的顏色是 last ,如last = 4 表示上一次用的是能塗 4 下的顏色中的某一個!
那麼我們怎麼轉移呢?
發現:
我們用現在能塗 一下的顏色塗色,就是
但是如果 我們上一次用的是能塗 2 下的顏色,那麼會產生什麼問題? 就是在這一次的時候它就變成的只能塗 1 下的顏色,所以現在的 a 種能塗 1 下 的顏色 我們只能選(a-1) 種 可能
以此類推下去…(看代碼就明白了!) 別忘了取模
//代碼故意留了一個小錯誤,希望是阻止大家直接ctrl+a,ctrl+c ! >_<
// luogu-judger-enable-o2
#pragma GCC optimize(3)
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#define ll long long
const ll MOD = 1000000007;
using namespace std;
int n,x,t[6];
ll dp[16][16][16][16][16][6];
inline ll DFS(int a,int b,int c,int d,int e,int last)
{
if(dp[a][b][c][d][e][last]!=-1) return dp[a][b][c][d][e][last];
if(a+b+c+d+e==0) return 1;
ll res = 0;
if(a) res += (a-(last==2)) * DFS(a-1,b,c,d,e,1);
if(b) res += (b-(last==3)) * DFS(a+1,b-1,c,d,e,2);
if(c) res += (c-(last==4)) * DFS(a,b+1,c-1,d,e,3);
if(d) res += (d-(last==5)) * DFS(a,b,c+1,d-1,e,4);
if(e) res += e * DFS(a,b,c,d+1,e-1,5);
dp[a][b][c][d][e][last] = res%MOD;
return dp[a][b][c][d][e][last];
}
int main(int argc, char const *argv[])
{
scanf("%d",&n);
for(;n;n--) scanf("%d",&x),t[x]++;
memset(dp,-1,sizeof dp);
printf("%lld\n",DFS(t[1],t[2],t[3],t[4],t[5],0));
return main();
}