传送门

这不是水题吗,你怎么还写题解啊?

。。。我也不知道颓啥了,随便水篇题解吧。

主要是我的图片存货急需倾泻要不然退役前放不完了

第一想法是存下所有颜色剩余次数,然而$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));
}