【SCOI2008】着色方案

[SCOI2008]着色方案

    • 題目描述

      有n個木塊排成一行,從左到右依次編號爲1~n。你有k種顏色的油漆,其

      中第i 種顏色的油漆足夠塗ci 個木塊。所有油漆剛好足夠塗滿所有木塊,即

      c1+c2+...+ck=n。相鄰兩個木塊塗相同色顯得很難看,所以你希望統計任意兩個相

      鄰木塊顏色不同的着色方案。

      輸入輸出格式

      輸入格式:

       

      第一行爲一個正整數k,第二行包含k個整數c1, c2, ... , ck。

       

      輸出格式:

       

      輸出一個整數,即方案總數模1,000,000,007的結果。

       

      輸入輸出樣例

      輸入樣例#1: 複製

      3
      1 2 3

      輸出樣例#1: 複製

      10

      我們設f[i][j]表示使用了前i種油漆,有j個相鄰的同色塊的方案數。

    • 考慮新加一種油漆i+1。我們假設有x個,我們先將他們分組。設分成了q組,那麼很顯然有C_{x-1}^{q-1}種方案,並且會新產生x-q個相鄰的顏色塊。我們還要將分好的組插入原來的木塊中間(包括兩邊),顯然有sum[i]+1個位置,其中有j個位置左右的顏色相同。我們在枚舉這q組中的k個(這一步有有C_{q}^{k}種方案)插入左右 顏色相同的位置(這一步有C_{j}^{k}中方案),其它的插入左右亞瑟不同的位置。插入過後顏色相同的數量變成了j+x-q-k。將前面的所有組合數乘起來,轉移方程就是f[i+1][j+x-q-k]+=f[i][j]*C_{x-1}^{q-1}*C_{j}^{k}*C_{q}^{k}

    • 開始想到的是同種

      顏色的油漆一個一個地加入,但是在加入的時候還要考慮相同顏色與不同顏色的塊要分開考慮,最後還要去重。。。就是各種複雜的操作,最後還是沒調出來。

    • 所以有些題適合逐個DP,有些適合一組一組地DP。

  •  

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<set>
    #include<map>
    #include<vector>
    #include<ctime>
    #define ll long long
    #define N 20
    #define mod 1000000007
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    int n;
    int sum[N],num[N];
    ll c[80][80],f[N][80];
    int main() {
    	c[0][0]=1;
    	for(int i=1;i<=75;i++)
    		for(int j=0;j<=i;j++)
    			c[i][j]=(!j||j==i)?1:(c[i-1][j-1]+c[i-1][j])%mod;
    	n=Get();
    	for(int i=1;i<=n;i++) {
    		num[i]=Get();
    		sum[i]=num[i]+sum[i-1];
    	}
    	f[1][num[1]-1]=1;
    	for(int i=1;i<n;i++) {
    		for(int j=0;j<=75;j++) {
    			if(!f[i][j]) continue ;
    			for(int q=1;q<=num[i+1];q++) {//分成q組 
    				if(q>sum[i]+1) continue ;
    				for(int k=0;k<=q;k++) {//其中k組放在相同塊中 
    					if(k>j||q-k>sum[i]+1-j||j+num[i+1]-q-k<0) continue ;
    					(f[i+1][j+num[i+1]-q-k]+=f[i][j]*c[num[i+1]-1][q-1]%mod*c[j][k]%mod*c[sum[i]+1-j][q-k])%=mod;
    				}
    			}
    		}
    	}
    	cout<<f[n][0];
    	return 0;
    }
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章