这不是水题吗,你怎么还写题解啊?
。。。我也不知道颓啥了,随便水篇题解吧。
主要是我的图片存货急需倾泻要不然退役前放不完了
第一想法是存下所有颜色剩余次数,然而$O(5^{15})$时空两开花。
$O(5^{15})$不行但是$O(15^5)=O(7\times 10^5)$是$OK$的。
记录每种剩余次数有多少种颜色和上一格涂的颜色是那种次数。
枚举这一格涂哪种次数,如果是上一格颜色的次数要减$1$,剩下的随便选乘一乘就好了。
状态数$5\times15^5$就可以愉快地记搜了。
代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define maxn 20
#define inf 0x3f3f3f3f
const int mod = 1e9 + 7;
using namespace std;
inline int read(){
int x=0,y=0;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')y=1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return y?-x:x;
}
int f[16][16][16][16][16][6];
int dfs(int tax[],int last=0){
if(tax[1]+tax[2]+tax[3]+tax[4]+tax[5]==0)return 1;
int *g=f[tax[1]][tax[2]][tax[3]][tax[4]][tax[5]]+last;
if(~(*g))return *g;
*g=0;
for(register int i=1;i<=5;++i)
if(tax[i]-(i+1==last)>0){
--tax[i],++tax[i-1];
(*g+=1ll*(tax[i]-(i+1==last)+1)*dfs(tax,i)%mod)%=mod;
++tax[i],--tax[i-1];
}
return *g;
}
int main(){
int n=read(),tax[6]={0},sum=0;
for(register int i=1;i<=n;++i)++tax[read()];
memset(f,-1,sizeof f);
printf("%d\n",dfs(tax));
}