每日一題 7月20日題目精講 著色方案

2021-10-08 10:48:38 字數 2328 閱讀 1415

時間限制:c/c++

1秒,其他語言2秒

空間限制:c/c++

262144k,其他語言524288k

64bit io format:

%lld

有n個木塊排成一行,從左到右依次編號為1~n。 你有k種顏色的油漆,其中第i種顏色的油漆足夠塗ci個木塊。

所有油漆剛好足夠塗滿所有木塊,即c1+c2+…+ck=n。

相鄰兩個木塊塗相同色顯得很難看,所以你希望統計任意兩個相鄰木塊顏色不同的著色方案。

輸入描述:

第一行為乙個正整數k,第二行包含k個整數c1, c2, … , ck。

輸出描述:

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

示例1

輸入

複製

312

3

輸出

複製

10
1<=k<=15 ,1<= ci

<=5

記憶化搜尋

dp[a][b][c][d][e][last]

表示每一種顏色分別剩下啊a,b,c,d,e個方案數,有a種乙個(可以塗1塊木塊的有多少種顏色),b種兩個,c種三個…e種五個,last表示上一次用的是可以塗last個木塊的油漆

因為我們不能連續塗兩塊相同的顏色,如果上一次用的還能塗i次的油漆,那麼當前就多一種還能塗i-1次的油漆未使用

所以如果b-1的話,a要+1,一次類推都是這樣

然後考慮轉移方程:

dp[a]

[b][c]

[d][e][1

]=dp[a-1]

[b][c]

[d][e][1

]*a+dp[a+1]

[b-1

][c]

[d][e][2

]*b+dp[a]

[b+1

][c-1]

[d][e][3

]*c+dp[a]

[b][c+1]

[d-1

][e][4

]*d+dp[a]

[b][c]

[d+1

][e-1]

[5]*e

我們在遞推中可以寫成這種形式

if

(a1) ans =

(ans +

1ll*

(a1 -

(last ==2)

)*dfs(a1 -

1, a2, a3, a4, a5,1)

)% mod;

(last==2)則是特判上一種顏色的種類,否則會造成重複

#include

const

int mod =

1e9+7;

using

namespace std;

typedef

long

long ll;

inline ll read()

while

(c >=

'0'&& c <=

'9')

return f * x;

}void

print

(ll x)

print

(x /10)

;putchar

(x %10+

48);}

ll dp[20]

[20][

20][20

][20]

[10];

int n, a[10]

; ll dfs

(int a1,

int a2,

int a3,

int a4,

int a5,

int last)

intmain()

for(

int i =

1; i <=

5; i++

) dp[0]

[0][

0][0

][0]

[i]=1;

print

(dfs

(a[1

], a[2]

, a[3]

, a[4]

, a[5]

,0))

;return0;

}

每日一題 7月20日題目精講 著色方案

時間限制 c c 1秒,其他語言2秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld有n個木塊排成一行,從左到右依次編號為1 n。你有k種顏色的油漆,其中第i種顏色的油漆足夠塗ci個木塊。所有油漆剛好足夠塗滿所有木塊,即c1 c2 ck n。相鄰兩個...

每日一題 4月7日題目精講 樹

樹 時間限制 c c 1秒,其他語言2秒 空間限制 c c 131072k 其他語言262144k 64bit io format lld 題目描述 shy有一顆樹,樹有n個結點。有k種不同顏色的染料給樹染色。乙個染色方案是合法的,當且僅當對於所有相同顏色的點對 x,y x到y的路徑上的所有點的顏色...

每日一題 7月1日題目精講 借教室

時間限制 c c 1秒,其他語言2秒 空間限制 c c 131072k,其他語言262144k 64bit io format lld 在大學期間,經常需要租借教室。大到院系舉辦活動,小到學習小組自習討論,都需要向學校申請借教室。教室的大小功能不同,借教室人的身份不同,借教室的手續也不一樣。面對海量...