有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块。 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两 个相邻木块颜色不同的着色方案。
标签:oid 相同 for ret == lld gre online nbsp
有n个木块排成一行,从左到右依次编号为1~n。你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块。 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n。相邻两个木块涂相同色显得很难看,所以你希望统计任意两 个相邻木块颜色不同的着色方案。
第一行为一个正整数k,第二行包含k个整数c1, c2, ... , ck。
输出一个整数,即方案总数模1,000,000,007的结果。
100%的数据满足:1 <= k <= 15, 1 <= ci <= 5
可以发现数量相同的颜色其实是等价的
那么记录一下每种数量的颜色个数以及上一步选了什么颜色
加加乘乘即可
#pragma GCC optimize("O2") #include <cstdio> typedef long long ll; const int mod = 1000000007; inline void add(ll &x, const ll &y){ x = (x + y) % mod; } bool mark[16][16][16][16][16][6] = {false}; ll f[16][16][16][16][16][6]; ll dp(int x1, int x2, int x3, int x4, int x5, int k){ if(x1 + x2 + x3 + x4 + x5 == 0) return 1; if(mark[x1][x2][x3][x4][x5][k]) return f[x1][x2][x3][x4][x5][k]; ll &ans = f[x1][x2][x3][x4][x5][k]; if(x1) add(ans, (x1 - (k == 2)) * dp(x1 - 1, x2, x3, x4, x5, 1)); if(x2) add(ans, (x2 - (k == 3)) * dp(x1 + 1, x2 - 1, x3, x4, x5, 2)); if(x3) add(ans, (x3 - (k == 4)) * dp(x1, x2 + 1, x3 - 1, x4, x5, 3)); if(x4) add(ans, (x4 - (k == 5)) * dp(x1, x2, x3 + 1, x4 - 1, x5, 4)); if(x5) add(ans, x5 * dp(x1, x2, x3, x4 + 1, x5 -1, 5)); mark[x1][x2][x3][x4][x5][k] = true; return ans; } int main(){ int k, c[6] = {0}; scanf("%d", &k); for(int t, i = 1; i <= k; i++){ scanf("%d", &t); c[t]++; } printf("%lld\n", dp(c[1], c[2], c[3], c[4], c[5], 1)); return 0; }
标签:oid 相同 for ret == lld gre online nbsp
原文地址:http://www.cnblogs.com/ruoruoruo/p/7633007.html