题目描述
有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其
中第i 种颜色的油漆足够涂ci 个木块。所有油漆刚好足够涂满所有木块,即
c1+c2+…+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相
邻木块颜色不同的着色方案。
输入输出格式
输入格式:
第一行为一个正整数k,第二行包含k个整数c1, c2, … , ck。
输出格式:
输出一个整数,即方案总数模1,000,000,007的结果。
题解
f[c1][c2][c3][c4][c5][last] f [ c 1 ] [ c 2 ] [ c 3 ] [ c 4 ] [ c 5 ] [ l a s t ] 表示上一个木块涂的颜色可以涂last块(包括上一块),能涂i块木块的颜色有ci种的最优解。
f[c1][c2][c3][c4][c5][last]+=
f
[
c
1
]
[
c
2
]
[
c
3
]
[
c
4
]
[
c
5
]
[
l
a
s
t
]
+
=
(c1−(last==2))∗f[c1−1][c2][c3][c4][c5][1]
(
c
1
−
(
l
a
s
t
==
2
)
)
∗
f
[
c
1
−
1
]
[
c
2
]
[
c
3
]
[
c
4
]
[
c
5
]
[
1
]
(c2−(last==3))∗f[c1+1][c2−1][c3][c4][c5][2]
(
c
2
−
(
l
a
s
t
==
3
)
)
∗
f
[
c
1
+
1
]
[
c
2
−
1
]
[
c
3
]
[
c
4
]
[
c
5
]
[
2
]
(c3−(last==4))∗f[c1][c2+1][c3−1][c4][c5][3]
(
c
3
−
(
l
a
s
t
==
4
)
)
∗
f
[
c
1
]
[
c
2
+
1
]
[
c
3
−
1
]
[
c
4
]
[
c
5
]
[
3
]
(c4−(last==5))∗f[c1][[c2][c3+1][c4−1][c5][4]
(
c
4
−
(
l
a
s
t
==
5
)
)
∗
f
[
c
1
]
[
[
c
2
]
[
c
3
+
1
]
[
c
4
−
1
]
[
c
5
]
[
4
]
c5∗f[c1][c2][c3][c4+1][c5][5]
c
5
∗
f
[
c
1
]
[
c
2
]
[
c
3
]
[
c
4
+
1
]
[
c
5
]
[
5
]
#include<cstdio>
#include<string>
using namespace std;
const int MOD=1e9+7;
long long K,num[6],f[16][16][16][16][16][6];
inline int read() {
int ret=0,f=1;char ch=getchar();
for (; !isdigit(ch); ch=getchar()) if (ch=='-') f=-f;
for (; isdigit(ch); ch=getchar()) ret=ret*10+ch-48;
return ret*f;
}
long long dfs(int c1,int c2,int c3,int c4,int c5,int last) {
if (f[c1][c2][c3][c4][c5][last]) return f[c1][c2][c3][c4][c5][last];
long long res=0;
if (c1) (res+=(c1-(last==2))*dfs(c1-1,c2,c3,c4,c5,1))%=MOD;
if (c2) (res+=(c2-(last==3))*dfs(c1+1,c2-1,c3,c4,c5,2))%=MOD;
if (c3) (res+=(c3-(last==4))*dfs(c1,c2+1,c3-1,c4,c5,3))%=MOD;
if (c4) (res+=(c4-(last==5))*dfs(c1,c2,c3+1,c4-1,c5,4))%=MOD;
if (c5) (res+=c5*dfs(c1,c2,c3,c4+1,c5-1,5))%=MOD;
return f[c1][c2][c3][c4][c5][last]=res;
}
int main() {
K=read();
for (int i=1; i<=K; i++) num[read()]++;
for (int i=1; i<=5; i++) f[0][0][0][0][0][i]=1;
printf("%lld\n",dfs(num[1],num[2],num[3],num[4],num[5],0));
return 0;
}