Problem Specification Value
Time Limit 10 Sec
Memory Limit 162 MB
Submit 1490
Solved 916

Description

有 n 个木块排成一行, 从左到右依次编号为 1~ n. 你有 k 种颜色的油漆, 其中第 i 种颜色的油漆足够涂 ci 个木块. 所有油漆刚好足够涂满所有木块, 即 c1+c2+...... +ck=n. 相邻两个木块涂相同色显得很难看, 所以你希望统计任意两个相邻木块颜色不同的着色方案.

Input

第一行为一个正整数 k, 第二行包含 k 个整数 c1, c2,. ...... , ck.

Output

输出一个整数, 即方案总数模 1, 000, 000, 007 的结果.

Sample Input

3
1 2 3

Sample Output

10

HINT

100% 的数据满足: 1 <=k <=15, 1 <=ci <=5

Source


直接集合 dp 肯定是不行的...... 考虑两种油漆如果当前都能涂 x 次, 那么他们本质是一样的.

所以用 F [a] [b] [c] [d] [e] [l] 表示当前有能涂 1 次的油漆 a 个, 能涂 2 次的 b 个…. 前一个颜色为 l, 再搞下转移就行了.

记忆化实现常数会小一些



#include <iostream>
#include <cstdlib>
#include <cstdio>

using namespace std;
typedef long long lld;
const int maxk = 16, maxc = 6;
const lld modr = 1000000007;

lld     dp_save[maxk][maxk][maxk][maxk][maxk][maxc];
bool    dp_used[maxk][maxk][maxk][maxk][maxk][maxc];
int     n, data[maxc];

lld dp(int a, int b, int c, int d, int e, int k)
{
    // a, b, c, d, e separately means the numbers of colours remaining, with the
    // respective remaining painting chances / counts to paint blocks, for 1, 2, 3,
    // 4, 5, respectively.
    // k means the last colour (count) used
    if (dp_used[a][b][c][d][e][k])
        return dp_save[a][b][c][d][e][k];
    if (a + b + c + d + e <= 0)
        return 1; // End of the line, about to recurse, say.
    lld sum = 0;
    if (a > 0) sum += (a - (k == 2)) * dp(a - 1, b, c, d, e, 1); // That was a trick.
    if (b > 0) sum += (b - (k == 3)) * dp(a + 1, b - 1, c, d, e, 2); // That was a trick.
    if (c > 0) sum += (c - (k == 4)) * dp(a, b + 1, c - 1, d, e, 3); // That was a trick.
    if (d > 0) sum += (d - (k == 5)) * dp(a, b, c + 1, d - 1, e, 4); // That was a trick.
    if (e > 0) sum += e * dp(a, b, c, d + 1, e - 1, 5); // That was a trick.
    // Updating saved changes...
    sum %= modr;
    dp_used[a][b][c][d][e][k] = true;
    dp_save[a][b][c][d][e][k] = sum;
    return sum;
}

int main(int argc, char** argv)
{
    scanf("%d", &n);
    for (int a, i = 1; i <= n; i++) {
        scanf("%d", &a);
        data[a]++;
    }
    lld res = dp(data[1], data[2], data[3], data[4], data[5], 0);
    printf("%lld\n", res);
    return 0;
}

from pydatagen import *
n = randrange(10, 16)
printf('%d\n' % n)
for i in range(0, n):
    printf('%d ' % randrange(1, 6))