bzoj1079 dp

不难的dp 然而我就是想不出

bzoj1079 dp
 1 #include<cstdio>

 2 #include<cstring>

 3 #include<cstdlib>

 4 #include<ctime>

 5 #include<algorithm>

 6 #include<iostream>

 7 #define rep(i,l,r) for(int i=l;i<r;i++)

 8 #define clr(a,x) memset(a,x,sizeof(a))

 9 #define mod 1000000007

10 typedef long long ll;

11 using namespace std;

12 int read()

13 {

14     char c=getchar();

15     int ans=0,f=1;

16     while(!isdigit(c)){

17         if(c=='-') f=-1;

18         c=getchar();

19     }

20     while(isdigit(c)){

21         ans=ans*10+c-'0';

22         c=getchar();

23     }

24     return ans*f;

25 }

26 const int maxk=16,maxn=76,maxc=6;

27 int sum[maxk],dd[maxk][maxk][maxk][maxk][maxk][maxk];

28 ll dp(int a,int b,int c,int d,int e,int pre)

29 {    

30     if(dd[a][b][c][d][e][pre]) return dd[a][b][c][d][e][pre];

31     if(a+b+c+d+e==0) return dd[a][b][c][d][e][pre]=1;

32     ll ans=0;

33     if(a) (ans+=(a-(pre==2))*dp(a-1,b,c,d,e,1))%=mod;

34     if(b) (ans+=(b-(pre==3))*dp(a+1,b-1,c,d,e,2))%=mod;

35     if(c) (ans+=(c-(pre==4))*dp(a,b+1,c-1,d,e,3))%=mod;

36     if(d) (ans+=(d-(pre==5))*dp(a,b,c+1,d-1,e,4))%=mod;

37     if(e) (ans+=e*dp(a,b,c,d+1,e-1,5))%=mod;

38     return dd[a][b][c][d][e][pre]=ans;

39 }

40 int main()

41 {    

42     clr(sum,0);

43     clr(dd,0);

44     int n=0,k=read();

45     rep(i,0,k){

46         int opt=read();

47         sum[opt]++;

48     }

49     ll ans=dp(sum[1],sum[2],sum[3],sum[4],sum[5],0);

50     cout<<ans%mod;

51     return 0;

52 }
View Code

1079: [SCOI2008]着色方案

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 1102  Solved: 698
[Submit][Status][Discuss]

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

 

Source

 
[ Submit][ Status][ Discuss]

你可能感兴趣的:(ZOJ)