bzoj1079 [SCOI2008]着色方案

来源:互联网 发布:存储过程实现数据同步 编辑:程序博客网 时间:2024/05/29 06:53

传送门
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
Sample Output

10
HINT

100%的数据满足:1 <= k <= 15, 1 <= ci <= 5

dp。
f[i][j][k][l][o][p]表示能有i种能用5次、j种能用4次、k种能用3次、l种能用2次、o种能用1次的油漆,最后用的一种能用p次的方案数。
由于代表的颜色不确定,所以在加的时候要乘以代表颜色的个数。同样,当用的这种油漆和之前一次的油漆能用的次数相同的时候,为了防止重复,要将其减掉。

这里写图片描述
时间效率好像有点慢……

CODE:

#include<cstdio>const int M=1e9+7;int num[6];int f[16][16][16][16][16][6];int m,t;inline void inc(int &x,int y){    x=(1ll*x+y)%M;}inline void dec(int &x,int &y){    x=(1ll*x-y+M)%M;}inline int mul(int &x,int &y){    int t=1ll*x*y%M;    return t;}int main(){    scanf("%d",&m);    for(int i=1;i<=m;i++)      scanf("%d",&t),num[t]++;    for(int i=0;i<=5;i++)      f[0][0][0][0][0][i]=1;    for(int i=0;i<=num[5];i++)      for(int j=0;j<=m;j++)        for(int k=0;k<=m;k++)          for(int l=0;l<=m;l++)            for(int o=0;o<=m;o++)              for(int p=0;p<=4;p++)              {                if(i) inc(f[i][j][k][l][o][p],mul(f[i-1][j+1][k][l][o][4],i));                if(j)                {                    inc(f[i][j][k][l][o][p],mul(f[i][j-1][k+1][l][o][3],j));                    if(p==4) dec(f[i][j][k][l][o][p],f[i][j-1][k+1][l][o][3]);                }                if(k)                {                    inc(f[i][j][k][l][o][p],mul(f[i][j][k-1][l+1][o][2],k));                    if(p==3) dec(f[i][j][k][l][o][p],f[i][j][k-1][l+1][o][2]);                }                if(l)                {                    inc(f[i][j][k][l][o][p],mul(f[i][j][k][l-1][o+1][1],l));                    if(p==2) dec(f[i][j][k][l][o][p],f[i][j][k][l-1][o+1][1]);                }                if(o)                {                    inc(f[i][j][k][l][o][p],mul(f[i][j][k][l][o-1][0],o));                    if(p==1) dec(f[i][j][k][l][o][p],f[i][j][k][l][o-1][0]);                }              }    printf("%d",f[num[5]][num[4]][num[3]][num[2]][num[1]][0]);    return 0;}
0 0
原创粉丝点击