牛客网 【每日一题】5月29日 管道取珠
鏈接:
文章目錄
- 題目描述
- 題意:
- 題解:
- 代碼:
題目描述
管道取珠是小X很喜歡的一款游戲。在本題中,我們將考慮該游戲的一個簡單改版。游戲畫面如圖1所示:
游戲初始時,左側上下兩個管道分別有一定數量的小球(有深色球和淺色球兩種類型),而右側輸出管道為空。每一次操作,可以從左側選擇一個管道,并將該管道中最右側的球推入右邊輸出管道。
例如,我們首先從下管道中移一個球到輸出管道中,將得到圖2所示的情況。
假設上管道中有n個球,下管道中有m個球,則整個游戲過程需要進行n+m次操作,即將所有左側管道中的球移入輸出管道。最終n
+m個球在輸出管道中從右到左形成輸出序列。
愛好數學的小X知道,他共有C(n+m, n)種不同的操作方式,而不同的操作方式可能導致相同的輸出序列。舉個例子,對于圖3所示的游戲情形:
我們用A表示淺色球,B表示深色球。并設移動上管道右側球的操作為U,移動下管道右側球的操作為D,則共有C(2+1,1)=3種不同的操作方式,分別為UUD,
UDU, DUU;最終在輸出管道中形成的輸出序列(從右到左)分別為BAB,BBA,BBA。可以發現后兩種操作方式將得到同樣的輸出序列。
假設最終可能產生的不同種類的輸出序列共有K種,其中第i種輸出序列的產生方式(即不同的操作方式數目)有ai個。聰明的小X早已知道,
因此,小X希望計算得到
你能幫助他計算這個值么?由于這個值可能很大,因此只需要輸出該值對1024523的取模即可(即除以1024523的余數)。
說明:文中C(n+m,n)表示組合數。組合數C(a,b)等價于在a個不同的物品中選取b個的選取方案數。
輸入描述:
第一行包含兩個整數n,m,分別表示上下兩個管道中球的數目。
第二行為一個AB字符串,長度為n,表示上管道中從左到右球的類型。其中A表示淺色球,B表示深色球。
第三行為一個AB字符串,長度為m,表示下管道中的情形。
輸出描述:
僅包含一行,即為除以1024523的余數
示例1
輸入
輸出
5題意:
總結下題目意思:
上下兩個管道,上管道有n個球,下管道有m個球,每次在上下取出一個球,球有黑有紅,取出會形成不同的系列,序列數為k,而同一種序列可能有不同取法,第i種序列,取法為a[i],
那會得到:所有取法的式子
問:
題解:
乍一看毫無思路,給了我們ai求和的公式,讓我們求ai2 求和的公式,這咋整。
注意,題目又臭又長給我們設定一個背景,是為了告訴我們所給的式子是具有物理含義的,題目中ai表示第i種序列的取法,ai求和是一個管道系統中所有取法的和。那ai2表示什么?不就表示兩個完全相同的管道系統,獨立取出小球,所得兩個管道系統序列相同的方案數量
這樣能想明白,接下來就好整
dp[k][i][j]表示兩個管道都取了k個球,第一個管道系統的第一個管道(上管道)取了i個球,自然第二個管道(第一個管道系統的下管道)取了k-i個球
同理:第二個管道系統的第一個管道取了j個球,第二個管道取了k-j個球
我們要得到相同序列,就要使得每次兩側取出的球都相同
然后轉移方程可得:
(圖中對四個管道進行標號)
a[]表示上管道球的顏色
b[]表示下管道球的顏色
dp[0][0][0]=1
有四種情況:
上A = = 上B (a[i] = = b[j]) dp [ k ] [ i ] [ j ]+=dp [ k-1 ] [ i - 1 ] [ j - 1 ] (同時在兩個的上管道取一個,這樣取出來就是相同序列)
上A = = 下B (a[i] = = b[k-j])dp[k][i][j]+=dp[k-1][i-1][j] (同時在第一個管道系統的上管道和第二個管道系統的下管道取一個球。第二個管道系統下管道取球,上管道不變,所以還是j)
下A = = 上B(b[k-i] = = a[j])dp[i][j][k]+=dp[k-1][i][j-1]
下A = = 下B (b[k-i] = = b[k-j]) dp[i][j][k]+=dp[k-1][i][j]
(其實就是兩邊管道當相同時自由組合)
我這樣講應該夠仔細了
對了,數組空間會超,所以用滾動數組來優化,降低復雜度
代碼:
狀態壓縮代碼參考
#include <bits/stdc++.h> using namespace std; const int maxn = 500 + 5; const int mod = 1024523; int dp[3][maxn][maxn]; int n, m; char a[maxn], b[maxn];int main() {cin >> n >> m;cin >> a + 1 ;cin >> b + 1;dp[0][0][0] = 1;for(int k = 1; k <= n + m; k++) {memset(dp[k&1], 0, sizeof dp[k&1]);for(int i = 0; i <= n; i++) {if(k - i < 0 || k - i > m) continue;for(int j = 0; j <= n; j++) {if(k - j < 0 || k - j > m) continue;if(i && j && a[i] == a[j])dp[k & 1][i][j]=(dp[k & 1][i][j]+dp[!(k & 1)][i - 1][j - 1])%mod;if(i && k - j && a[i] == b[k - j])dp[k & 1][i][j] =(dp[k & 1][i][j]+ dp[!(k & 1)][i - 1][j])%mod;if(k - i && j && b[k - i] == a[j])dp[k & 1][i][j]=(dp[k & 1][i][j] + dp[!(k & 1)][i][j - 1])%mod;if(k - i && k - j && b[k - i] == b[k-j])dp[k & 1][i][j]=(dp[k & 1][i][j] + dp[!(k & 1)][i][j])%mod;}}}cout << dp[(n + m) & 1][n][n] << endl;return 0; }總結
以上是生活随笔為你收集整理的牛客网 【每日一题】5月29日 管道取珠的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 牛客网 【每日一题】5月28日题目精讲
- 下一篇: 怎么用ps画花(怎么用ps画花朵)