题目描述
有n个木块排成一行,从左到右依次编号为1~n。
你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块。 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n。
相邻两个木块涂相同色显得很难看,所以你希望统计任意两个相邻木块颜色不同的着色方案。
输入描述:
第一行为一个正整数k,第二行包含k个整数c1, c2, ... , ck。
输出描述:
输出一个整数,即方案总数模1,000,000,007的结果
题解
一共有15种颜色,如果直接从颜色入手会比较麻烦,
我们考虑存储剩余能涂x个木块的油漆有多少种。
设置dp[a][b][c][d][e][last]为还剩a种可以涂1个块的油漆,还剩b种可以涂2个块的油漆,还剩c种可以涂3个块的油漆,还剩d种可以涂4个块的油漆,还剩e种可以涂5个块的油漆,以及上一次涂的油漆是可以涂last个块的。
首先,当前选什么样的颜色不重要,只需满足不相邻条件就可以。举个例子,假设你要选还可以涂3个块的颜色,只需让c或者c-1乘上dp[a][b+1][c-1][d][e][last]就行。
因为如果你选了还可以涂3个块的颜色,选完以后它就变成了还可以涂2个块的颜色,所以我们需要让b+1同时c-1。
除此之外,上次选了还可以涂4个块的颜色,如果这次要选还可以涂3个块的颜色,那就不能再选上次选过的颜色,此时就应该乘以c-1才可以。
代码
#include<iostream> #include<algorithm> #include<map> #include<vector> #include<set> #include<string> #include<cstring> #include<cstdio> #include<cmath> #include<queue> #include<stack> using namespace std; #define ll long long #define ull unsigned long long #define pb push_back #define pii pair<int,int> #define all(A) A.begin(), A.end() #define fi first #define se second #define MP make_pair #define rep(i,n) for(register int i=0;i<(n);++i) #define repi(i,a,b) for(register int i=int(a);i<=(b);++i) #define repr(i,b,a) for(register int i=int(b);i>=(a);--i) template<typename T> inline T read(){ T s=0,f=1; char ch = getchar(); while(!isdigit(ch)) {if(ch == '-') f=-1;ch = getchar();} while(isdigit(ch)) {s=(s<<3)+(s<<1)+ch-48;ch = getchar();} return s*f; } #define gn() read<int>() #define gl() read<ll>() template<typename T> inline void print(T x) { if(x<0) putchar('-'), x=-x; if(x>9) print(x/10); putchar(x%10+'0'); } //////////////////////////////////////////////////////////////////////// const int N=2e5+100; const int mod=1e9+7; int c[6]; ll dp[20][20][20][20][20][6]; ll dfs(int c1,int c2,int c3,int c4,int c5,int lst){ if(dp[c1][c2][c3][c4][c5][lst]) return dp[c1][c2][c3][c4][c5][lst]; ll rst=0; if(c1) rst+=(c1-(lst==2))*dfs(c1-1,c2,c3,c4,c5,1); if(c2) rst+=(c2-(lst==3))*dfs(c1+1,c2-1,c3,c4,c5,2); if(c3) rst+=(c3-(lst==4))*dfs(c1,c2+1,c3-1,c4,c5,3); if(c4) rst+=(c4-(lst==5))*dfs(c1,c2,c3+1,c4-1,c5,4); if(c5) rst+=(c5)*dfs(c1,c2,c3,c4+1,c5-1,5); return dp[c1][c2][c3][c4][c5][lst]=rst%mod; } //////////////////////////////////////////////////////////////////////// int main(){ int k=gn(); repi(i,1,5) dp[0][0][0][0][0][i]=1; repi(i,1,k){ int x=gn(); ++c[x]; } print(dfs(c[1],c[2],c[3],c[4],c[5],0)); return 0; } /** * In every life we have some trouble * When you worry you make it double * Don't worry,be happy. **/