时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
有n个木块排成一行,从左到右依次编号为1~n。 你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块。
所有油漆刚好足够涂满所有木块,即c1+c2+…+ck=n。
相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相邻木块颜色不同的着色方案。
输入描述:
第一行为一个正整数k,第二行包含k个整数c1, c2, … , ck。
输出描述:
输出一个整数,即方案总数模1,000,000,007的结果。
示例1
输入
复制
3
1 2 3
输出
复制
10
1<=k<=15 ,1<= ci <=5
题解:
记忆化搜索
dp[a][b][c][d][e][last]
表示每一种颜色分别剩下啊a,b,c,d,e个方案数,有a种一个(可以涂1块木块的有多少种颜***种两个,c种三个…e种五个,last表示上一次用的是可以涂last个木块的油漆
因为我们不能连续涂两块相同的颜色,如果上一次用的还能涂i次的油漆,那么当前就多一种还能涂i-1次的油漆未使用
所以如果b-1的话,a要+1,一次类推都是这样
然后考虑转移方程:
dp[a][b][c][d][e][1]=dp[a-1][b][c][d][e][1]*a+dp[a+1][b-1][c][d][e][2]*b+dp[a][b+1][c-1][d][e][3]*c+dp[a][b][c+1][d-1][e][4]*d+dp[a][b][c][d+1][e-1][5]*e
我们在递推中可以写成这种形式
if(a1) ans = (ans + 1ll * (a1 - (last == 2)) * dfs(a1 - 1, a2, a3, a4, a5, 1)) % mod;
(last==2)则是特判上一种颜色的种类,否则会造成重复
代码:
#include <bits/stdc++.h>
const int mod = 1e9 + 7;
using namespace std;
typedef long long ll;
inline ll read() {
ll f = 1, x = 0;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return f * x;
}
void print(ll x) {
if(x < 10) {
putchar(x + 48);
return ;
}
print(x / 10);
putchar(x % 10 + 48);
}
ll dp[20][20][20][20][20][10];
int n, a[10];
ll dfs(int a1, int a2, int a3, int a4, int a5, int last) {
if(dp[a1][a2][a3][a4][a5][last]) return dp[a1][a2][a3][a4][a5][last];
ll ans = 0;
if(a1) ans = (ans + 1ll * (a1 - (last == 2)) * dfs(a1 - 1, a2, a3, a4, a5, 1)) % mod;
if(a2) ans = (ans + 1ll * (a2 - (last == 3)) * dfs(a1 + 1, a2 - 1, a3, a4, a5, 2)) % mod;
if(a3) ans = (ans + 1ll * (a3 - (last == 4)) * dfs(a1, a2 + 1, a3 - 1, a4, a5, 3)) % mod;
if(a4) ans = (ans + 1ll * (a4 - (last == 5)) * dfs(a1, a2, a3 + 1, a4 - 1, a5, 4)) % mod;
if(a5) ans = (ans + 1ll * a5 * dfs(a1, a2, a3, a4 + 1, a5 - 1, 5)) % mod;
return dp[a1][a2][a3][a4][a5][last] = ans;
}
int main() {
n = read();
for(int i = 1; i <= n; i++) {
int x = read();
a[x]++;
}
for(int i = 1; i <= 5; i++) dp[0][0][0][0][0][i] = 1;
print(dfs(a[1], a[2], a[3], a[4], a[5], 0));
return 0;
}