题目描述
有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.
**/
京公网安备 11010502036488号