有乙個長度為 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 首先將所有的數異或,因為有兩個數出現一次,所以最終得到的異或結果,...