1079: [SCOI2008]着色方案
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1820 Solved: 1092
[ Submit][ Status][ Discuss]
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
1 2 3
Sample Output
10
HINT
100%的数据满足:1 <= k <= 15, 1 <= ci <= 5
还是太naive了qaq以为是数学题做了半天。。。其实dp就行了
#include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; typedef long long LL; inline LL read() { LL x=0;bool f=0;char c=getchar(); for (;c<'0'||c>'9';c=getchar()) f=c=='-'?1:0; for (;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0'; return f?-x:x; } const int mod=1000000007; int k,num[6]; LL f[16][16][16][16][16][6]; bool v[16][16][16][16][16][6]; LL dfs(int n1,int n2,int n3,int n4,int n5,int c) { if (v[n1][n2][n3][n4][n5][c]) return f[n1][n2][n3][n4][n5][c]; if (n1+n2+n3+n4+n5==0) return 1; LL rec=0; if (n1) rec+=dfs(n1-1,n2,n3,n4,n5,1)*(n1-(c==2)); if (n2) rec+=dfs(n1+1,n2-1,n3,n4,n5,2)*(n2-(c==3)); if (n3) rec+=dfs(n1,n2+1,n3-1,n4,n5,3)*(n3-(c==4)); if (n4) rec+=dfs(n1,n2,n3+1,n4-1,n5,4)*(n4-(c==5)); if (n5) rec+=dfs(n1,n2,n3,n4+1,n5-1,5)*n5; v[n1][n2][n3][n4][n5][c]=1; return f[n1][n2][n3][n4][n5][c]=rec%mod; } int main() { k=read(); for (int i=1;i<=k;i++) num[read()]++; printf("%d\n",dfs(num[1],num[2],num[3],num[4],num[5],0)); return 0; }