项目编号:bzoj-1079

项目等级:Safe

项目描述:

  戳这里

特殊收容措施:

  DP。普通的状压状态数515,显然TLE+MLE,我们考虑把底数和幂换一换,压成155的状态数。

  故状态设计为:f[last][rest1][rest2][rest3][rest4][rest5],表示上一个颜色为last,剩余k个方块的颜色种类数为restk的涂色方案数。

  然后DP或记忆化即可。复杂度o(5k5)。

附录:

 1 #include <bits/stdc++.h>
 2 #define range(i,c,o) for(register int i=(c);i<(o);++i)
 3 #define dange(i,c,o) for(register int i=(c);i>(o);--i)
 4 using namespace std;
 5  
 6 static const int AwD=1000000007; static int n;
 7 int r[5],f[5][20][20][20][20][20];
 8  
 9 int DP(const int&las)
10 {
11     if(!r[0]&&!r[1]&&!r[2]&&!r[3]&&!r[4]) return 1;
12     if(~f[las][r[0]][r[1]][r[2]][r[3]][r[4]])
13     {
14         return f[las][r[0]][r[1]][r[2]][r[3]][r[4]];
15     }
16     int ret=0;
17     range(col,0,5) if(r[col])
18     {
19         --r[col]; if(col) ++r[col-1];
20         if(int cnt=r[col]+(col+1!=las))
21         {
22             (ret+=1ll*DP(col)*cnt%AwD)%=AwD;
23         }
24         ++r[col]; if(col) --r[col-1];
25     }
26     return f[las][r[0]][r[1]][r[2]][r[3]][r[4]]=ret;
27 }
28  
29 int main()
30 {
31     scanf("%d",&n),memset(f,-1,sizeof f);
32     range(i,0,n) {int c; scanf("%d",&c),++r[c-1];}
33     return printf("%d\n",DP(0)),0;
34 }
View Code