由于最终的染色只与ci为几的个数有关,因此定义状态f[a][b][c][d][e][p]表示有a个ci=1,b个ci=2,……,有e个ci=5,上一次选择了ci=p的。状态的转移:发现p会让p-1少选一次,因此可以写出方程(详见代码),可以用记忆化搜索来写。
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long n,k,s[6],f[16][16][16][16][16][6]; 4 long long dfs(int a,int b,int c,int d,int e,int p){ 5 if (f[a][b][c][d][e][p])return f[a][b][c][d][e][p]; 6 if (a)f[a][b][c][d][e][p]+=(a-(p==2))*dfs(a-1,b,c,d,e,1); 7 if (b)f[a][b][c][d][e][p]+=(b-(p==3))*dfs(a+1,b-1,c,d,e,2); 8 if (c)f[a][b][c][d][e][p]+=(c-(p==4))*dfs(a,b+1,c-1,d,e,3); 9 if (d)f[a][b][c][d][e][p]+=(d-(p==5))*dfs(a,b,c+1,d-1,e,4); 10 if (e)f[a][b][c][d][e][p]+=e*dfs(a,b,c,d+1,e-1,5); 11 return f[a][b][c][d][e][p]=f[a][b][c][d][e][p]%1000000007+1000000007; 12 } 13 int main(){ 14 scanf("%lld",&n); 15 for(int i=1;i<=n;i++){ 16 scanf("%lld",&k); 17 s[k]++; 18 } 19 for(int i=1;i<=5;i++)f[0][0][0][0][0][i]=1; 20 printf("%lld",dfs(s[1],s[2],s[3],s[4],s[5],0)-1000000007); 21 }