有關排列的dp題目

2021-09-12 19:54:25 字數 1463 閱讀 7559

有乙個長度為 n

nn 的排列 a

aa,其中有一些位置被替換成了 -1。你需要嘗試恢復這個排列,將 -1 替換回數字。求有多少種可行的替換方法,滿足得到的是乙個排列,且不存在 ai=

ia_i = i

ai​=

i 的。

n

≤5000

n\leq 5000

n≤5000

前置技巧:乙個每行、每列只有乙個棋子的棋盤,任意交換行列,得到的棋盤每行、每列只有乙個棋子。

在序列裡填排列,某些位置有限制。想到把問題轉化為在 n∗n

n*nn∗

n 的棋盤上填放棋子,對角線不能放,有些格仔已經放了。我們把已經放石子的行、列刪除,就變成了在乙個棋盤上有若干個點不能放,且每行每列最多只有乙個限制。容易發現我們並不關心限制的位置,因此可以強制通過行列交換使得限制為對角線上的乙個字首。設 f[i

][j]

f[i][j]

f[i][j

] 表示 i∗i

i*ii∗

i 的棋盤裡有 j

jj 個限制的方案數,那麼考慮 f[i

][j]

f[i][j]

f[i][j

] 比 f[i

][j−

1]

f[i][j-1]

f[i][j

−1] 少了那些狀態,就是那些 (j,

j)

(j,j)

(j,j

) 放了石子的狀態。因此 f[i

][j]

=f[i

][j−

1]−f

[i−1

][j−

1]

f[i][j]=f[i][j-1]-f[i-1][j-1]

f[i][j

]=f[

i][j

−1]−

f[i−

1][j

−1]。

給定自然數n、k、x,你要求出第k小的長度為n的逆序對對數為x的1~n的排列。

考慮逐位確定這個排列。假設 1…i

−1

1\dots i-1

1…i−

1 都已經填好,我們要確定第 i

ii 個數填什麼。列舉乙個數 j

jj,我們想要知道如果這一位填 ≤

j\le j

≤j的數後面隨便填的合法排列數量記為 sum

jsum_j

sumj

​,如果 sum

j<

ksum_j< k

sumj

​<

k 並且 sum

j+1≥

ksum_\ge k

sumj+1

​≥k,那麼這一位就填 jjj。

發現列舉了乙個數以後已經填數的部分逆序對數已知,我們要求的就是「 i

ii 個數的排列裡逆序對數量為 j

jj 的有多少個」。顯然可以 dp 出來。

有關棧的題目

設計包含min函式的棧。定義棧的資料結構,要求新增乙個min函式,能夠得到棧的最小元素。要求函式min push以及pop的時間複雜度都是o 1 結合鍊錶一起做。容器vector代替鍊錶 eg 10,3,3,8,2,6 1.push 如果push入棧a的元素小於棧b的棧頂所對應的的元素,則將該元素p...

幾個有關棧的題目

棧 stack 是限定僅在表尾進行插入或刪除操作的線性表。棧又稱為後進先出 last in first out 的線性表 簡稱lifo結構 對於棧來說,表尾端有其特殊含義,稱為棧頂 top 相應的,表頭端稱為棧底 bottom 棧的順序儲存空間為s 1 50 s 1 m 答 這裡的 1 50 和 1...

有關異或的題目

異或 相同數字得到0,任何數與零異或,最終得到自身,同時異或滿 換律。include include intmain int result 0 for int j 0 j sizeof a 4 1 j printf d result 首先將所有的數異或,因為有兩個數出現一次,所以最終得到的異或結果,...