鍵盤上有左括號(,右括號),和退格鍵-,共三個鍵。
牛牛希望按鍵n次,使得輸入的字串恰好乙個合法的括號序列。
每按一次左括號(,字串末尾追加乙個左括號(
每按一次右括號),字串末尾追加乙個右括號)
每按一次退格鍵-,會刪掉字串的最後乙個字元,
特別的,如果字串為空,牛牛也可以按退格,但是什麼都不會發生。
輸出方案數對p取模,注意p可能不是質數。
注:只要按鍵方法不同,就是不同的方案,即使得到的序列一樣。
solution
這題和其他關於括號序列的題不太一樣,因為有了刪除操作。
由於我太zz,然後搞了個*b方程。
設dp[i][j]表示按了i次,造出了乙個長度為j的序列的方案數。
轉移是dp[i][j]=dp[i-1][max(0,j-1)]+dp[i-1][j+1]
這裡取max是指當序列為空時我也可以退格。
然後我們就有了乙個長度為j的序列,我們要把左括號和右括號往裡放,使得它是乙個合法的括號序列。
其實這個方案數就是卡特蘭數。
於是我們列舉長度,答案加上dp[n][i]*catalan(i/2)。
然後樣例**。
發現(+del和)+del最後製造出的序列是一樣的,但是是兩種不同的方案,但按照上面的方法dp只會計算一次。
所以刪除時要考慮刪什麼字元。
正確轉移方程:dp[i][j]=dp[i-1][max(0,j-1)]+dp[i-1][j+1]*2.
code
#include#include#define n 1002
using
namespace
std;
typedef
long
long
ll;int
n;ll f[n][n],dp[n][n],p,ans;
intmain()
for(int i=0;i<=n;i+=2)(ans+=(f[i][0]*dp[n][i])%p)%=p;
printf(
"%lld\n
",ans);
return0;
}
組合數學 序列統計
題解 生成乙個長度為1 n的序列,在l,r區間中選擇數字。那麼有m r l 1個數字可以選擇,每個數字選擇的次數加起來為n,所以這是明顯的插空法。為了讓每個數字都一定會被選一次,所以左右全部 1,接下裡就是利用公式合併再盧卡斯一下了。pragma gcc optimize 2 include def...
合法括號序列
合法括號序列 鍵盤上有左括號 右括號 和退格鍵 共三個鍵。牛牛希望按鍵n次,使得輸入的字串恰好乙個合法的括號序列。每按一次左括號 字串末尾追加乙個左括號 每按一次右括號 字串末尾追加乙個右括號 每按一次退格鍵 會刪掉字串的最後乙個字元,特別的,如果字串為空,牛牛也可以按退格,但是什麼都不會發生。輸出...
組合數學 求組合數
對於求組合數,要根據所給資料範圍來選擇合適的演算法 這道題中所給的資料範圍適合用打表的方法直接暴力求解 先用4e6的複雜度預處理出所有的情況,再用1e4的複雜度完成詢問即可 include using namespace std const int n 2010 const int mod 1e9 ...