bzoj 1079: [SCOI2008]著色方案
阿新 • • 發佈:2017-08-26
我沒 組合 滿足 b- col line 模擬 lose 同學
1 2 3
1079: [SCOI2008]著色方案
2017-08-26
Description
有n個木塊排成一行,從左到右依次編號為1~n。你有k種顏色的油漆,其中第i種顏色的油漆足夠塗ci個木塊。
所有油漆剛好足夠塗滿所有木塊,即c1+c2+...+ck=n。相鄰兩個木塊塗相同色顯得很難看,所以你希望統計任意兩
個相鄰木塊顏色不同的著色方案。
Input
第一行為一個正整數k,第二行包含k個整數c1, c2, ... , ck。
Output
輸出一個整數,即方案總數模1,000,000,007的結果。
Sample Input
31 2 3
Sample Output
10HINT
100%的數據滿足:1 <= k <= 15, 1 <= ci <= 5
一開始想按照某鱉棋那樣子暴力的,一共開15維。。(肯定不對的說,時間空間都不對);
那看ci<=5what?數字蠻小的的說,那就可以枚舉每個染料的個數。
前五維是每一個顏料剩余i的顏色總個數;最後一維是上一次染色。
總之很玄學。
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #define ll long long using namespace鱉std; const ll mod=1000000007; int a[10],n,t; ll dp[16][16][16][16][16][6]; bool rem[16][16][16][16][16][6]; ll F(int a,int b,int c,int d,int e,int k){ if(a+b+c+d+e==0){ rem[a][b][c][d][e][k]=dp[a][b][c][d][e][k]=1;return 1;} if(dp[a][b][c][d][e][k])return dp[a][b][c][d][e][k]; ll t=0; if(a)t+=(a-(k==2))*F(a-1,b,c,d,e,1); if(b)t+=(b-(k==3))*F(a+1,b-1,c,d,e,2); if(c)t+=(c-(k==4))*F(a,b+1,c-1,d,e,3); if(d)t+=(d-(k==5))*F(a,b,c+1,d-1,e,4); if(e)t+=(e)*F(a,b,c,d+1,e-1,5); rem[a][b][c][d][e][k]=1;dp[a][b][c][d][e][k]=t%mod; return t%mod; } int main(){ cin>>n; for(int i=1;i<=n;i++){cin>>t;a[t]++;} cout<<F(a[1],a[2],a[3],a[4],a[5],0)%mod; return 0; }
by:s_a_b_e_r
最近s同學學會了讀入優化
還沒看題先開始寫讀入優化
於是看到數據範圍之後……ww
一開始各種瞎想……組合數?容斥?
想不出來.jpg
後來看了題解,記憶化搜索
因為如果兩種油漆剩余使用次數一樣的話,可以看做等效的說
f[a][b][c][d][e][l]表示剩余1次的油漆有a種……剩余5次的油漆有e種,l表示上次塗的顏色
如果上一次用的是l油漆,這一次就不能再塗l油漆
於是就有了這個神奇的轉移方程
#include<iostream> #include<cstdio> using namespace std; const int M=1000000007; int k,c[10]; long long f[16][16][16][16][16][6]; long long dp(int a,int b,int c,int d,int e,int l) { if(a+b+c+d+e==0)return 1; if(f[a][b][c][d][e][l])return f[a][b][c][d][e][l]; long long t=0; if(a)t+=(a-(l==2))*dp(a-1,b,c,d,e,1); if(b)t+=(b-(l==3))*dp(a+1,b-1,c,d,e,2); if(c)t+=(c-(l==4))*dp(a,b+1,c-1,d,e,3); if(d)t+=(d-(l==5))*dp(a,b,c+1,d-1,e,4); if(e)t+=e*dp(a,b,c,d+1,e-1,5); f[a][b][c][d][e][l]=t%M; return f[a][b][c][d][e][l]; } int main() { cin>>k; int x; for(int i=1;i<=k;++i){cin>>x;++c[x];} long long ans=dp(c[1],c[2],c[3],c[4],c[5],0)%M; cout<<ans<<endl; return 0; }1079(wypx)
s:=wow=,點兔的音樂太好了,害得我沒法專心打oi模擬賽了
w:快把你耳機摘下來……等等我先把我耳機摘下來x
bzoj 1079: [SCOI2008]著色方案