題意:
給你1~n的排列,全部插入雙端佇列,最終佇列必須滿足1的左邊數列遞減,右邊遞增,即乙個v型,再以任意順序全部彈出。問第k個彈出的數為1的方案有多少種(mod 1e9+7),注意,兩個方案當且僅當它們某一次彈出的數不同時視為不同。
題解:
首先我們要推出個有用的結論來轉化題意,在這裡,我們的重點是每次彈出的數。我們注意到每次能彈出的數為隊首或隊尾,要麼是左邊最大,要麼是右邊最大,顯然其中乙個必然是剩下全部數中最大的,不妨設是隊首。又因為以前左邊彈出的數都比隊首大,右邊彈出的數都比隊尾大,所以隊尾必然比所有以前彈出的所有數都小,所以隊尾必然比最小值小。整理一下,每次能彈出的數只有兩種可能
1. 沒彈的數中最大
2. 比已彈出的數中最小還要小用d
p[i]
[j] dp[
i][j
]表示已彈i個數,這i個數的最小值為j的方案數。
轉移時有兩種情況:一種是這次(第
i i
次)彈出j,那麼只要上一次時最小值大於j即可,同時這時j滿足條件2,所以可以彈出j;因為是排列,只有乙個j,所以這種情況下方案數為∑k
=j+1
ndp[
i−1]
[k]∗
1' role="presentation" style="position: relative;">∑nk
=j+1
dp[i
−1][
k]∗1
∑k=j
+1nd
p[i−
1][k
]∗1
另一種是以前最小為j,這次彈出數比j大,要轉移過來的狀態顯然為dp[i-1][j],但這時要滿足i+
j−1≤
n i+j
−1≤n
剩下的數中才有比j大的數,否則這種情況下方案數為0。在剩下的數中有比j大的數的情況下,條件2顯然不能滿足(要彈出的數比j大),對於dp[i-1][j]中每一種確定的方案,沒彈出的數字也確定了,因為是排列,沒彈的數中最大的數也只有對應的乙個,所以這種情況下方案數為dp
[i−1
][j]
∗1d p[
i−1]
[j]∗
1那麼最終方程為dp
[i][
j]=∑
nk=j
dp[i
−1][
k]d p[
i][j
]=∑k
=jnd
p[i−
1][k
],用s[i]陣列做字首和優化,時間複雜度為o(n2
n 2)
**:
#include
#include
using
namespace
std;
#define n 2005
const
int mod=1e9+7;
int n,k;
int dp[n][n],ss[n];
int mul(int a,int b)
return ret;
}int ksm(int a,int p)
return ret;
}int main()
printf("%d\n",mul(ksm(2,n-k-1),((dp[k][1]-dp[k-1][1])%mod+mod)%mod));
return
0;}
18年小結(一)
昨天過了33歲的生日。在 西遊記後傳 中,33年是乙個輪迴週期的數字,希望自己的人生也進入乙個新的階段吧。2018年已經過去了三分之二。我在這個2018所經歷的,幾乎是顛覆了自己這七八年來所建立的大部分認知和行事準則 最大程度的去接受變化和不確定性。要用乙個字總結現在的感受,就是 累 為什麼會累呢?...
實驗一中的OOP思想
子類繼承父類 父類中宣告了介面變數 介面ab中宣告了抽象方法 ab 在子類中 可以用這樣通俗的語句寫程式 while this.termination.shouldterminate pnew.g this.unary.mutate pnew.g,this.random pnew.x this.gp...
勞傷解(一) 中氣
原文 脾為己土,以太陰而主公升,胃為戊土,以陽明而主降。公升降之權,則在陰陽之交,是謂中氣。脾是已土,沿著太陰經而且主公升,胃是戊土,沿著陽明經而且主降,公升降的權利,則是在於陰陽的相交,這就是中氣。胃主受盛,脾主消磨,中氣旺則胃降而善納,脾公升而善磨,水谷腐熟,精氣滋生,所以無病。胃主要負責接受和...