題目鏈結有(n
+m)(
n+m)
個字母a和(n+
m)(n
+m)個字母b,組成乙個長度為 2∗(
n+m)
2∗(n
+m)的字串,並且使得字串中有n
n個「ab」和m
m個「ba」,求出可能的組合數(mod 1e9+7)
例如,n = 1 m = 2時,可以有這樣的字串(並不是全部的字串):
abbaba
abbbaa
bbabaa
上面三個字串均滿足條件
考慮遞推,假設已經有乙個字串滿足一定的「先決條件」(此處應當理解為數學歸納法,及假設n - 1時滿足)
下面考慮在字串最後加入乙個字元的情況。僅有兩種可能:加a或者加b(這不是白說嗎)
但是考慮一下極端情況,我們可以得到一些簡單的且明顯的條件(na表示已經在字串中的a個數,nb同理)
假如字串的組成類似這樣:
aaaaabbbbbbbb則此字串中,只能組合出 ab 而不可能組合出 ba
此時,我們假設 n
n 為 5
而這個字元只能且必定要組合成 5 個ab,也就是說,我們接下來加入字元,只能加入 a 而不能加入 b
此時我們往前推,如果出現了這樣乙個字串,則在之前,必定出現如下狀態:
aaaaa也即是 5 個a的情況,此時我們可以得到乙個確定的關係式:
nb = 0 and na推廣到有b的情況,最優的情況就是所有的b都是用來組成ba,那麼可以得到我們真正需要的關係式:<= n
na - nb同理,相對於 b 而言,我們可以得到<= n
nb - na合併上述兩式<= m
-n < na - nb所以根據下標為 na - nb 建立dp陣列,下標範圍為 -n 到 m (均包含)dp的內容為方案數量(mod 1e9 + 7),遞推公式為dp<= m
[i]=
dp[i
−1]+
dp[i
+1]d
p[i]
=dp[
i−1]
+dp[
i+1]
其中,dp[i - 1]指的是加入乙個b(增加乙個b使得na - nb變小)。而dp[i + 1]指的是加入乙個a
當考慮到無論是正向dp還是逆向dp,均有值優先於dp[i]先更新(dp[i - 1]和dp[i + 1]會比dp[i]先更新),所以採用兩個dp陣列的方式,初始值dp[0]=1。每兩次dp完後,dp[0]的值及為答案。
#include
using namespace std;
#define maxn 2100
#define mod (int)(1e9 + 7)
typedef
long
long ll;
ll dp[maxn][2
];inttrans
(int x)
intmain()
if(j != m)
}for
(int j =
-n; j <= m; j++
)swap
(cur, last);}
cout << dp[n]
[last]
<< endl;
}return0;
}
2023年牛客多校第一場 E題 ABBA DP
傳送門首先我們知道 a 在放了 n 個位置裡面是沒有約束的,b 在放了 m 個位置裡面也是沒有約束的,其他情況見下面情況討論。dp i j 表示放了 i 個 a 和 j 個 b 的方案數,然後考慮轉移到下乙個狀態 include include include include include inc...
2019牛客多校第一場
看到這裡我還能說什麼呢?自己慢慢證吧 就是這個 而 了 大佬們的結論是 三角形面積的22倍。我.手動膜拜。不會證.while true try x1,y1,x2,y2,x3,y3 map int,input split s abs x1 y2 x2 y1 x2 y3 x3 y2 x3 y1 x1 y...
2019 牛客多校 第一場
a 題意 就是兩個陣列,找最大的p,使對於1到p的所有子區間都保證最小值的下標相同 題解 每次往後加乙個值 第i 1位 都會多出 i 個區間,當a i 1 大於max a 1 a i 時沒有影響,當a i 小於max a 1 a i 時,因為a i 1 的加入會導致區間的rmq l到r 的 最小值的...