數學
排列組合
錯排問題:\(D_n=(n-1)(D_{n-1}+D_{n-2})\) \((D_1=0,D_2=1)\)
資料結構
棧
出棧序列數量 卡特蘭數\(\displaystyle C_i=\frac{C^n_{2n}}{n+1}=\sum_{i=0}^{n} {C_i}{C_{n-i}}\)
樹
一個結點的度為這個節點的子節點數,一棵樹的度為所有節點的度數最大值
二叉樹
- 二叉樹中,編號為i的結點,父結點為\(\lfloor \frac{i}{2} \rfloor\),子結點分別為\(2i\)和\(2i+1\)
- 第\(i\)層最多有\(2^{i-1}\)個結點,深度為\(k\)的樹最多有\(2^k-1\)個結點
- \(N=N_0+N_1+N_2\),\(N_2+1=N_0\)
圖
有關定義
- 不存在重邊與自環的圖,叫做簡單圖
- 無向圖中任意兩個結點間都存在邊相連,叫做無向完全圖
- 有向圖中任意兩個結點間都存在互為相反的兩條邊相連,叫做有向完全圖
- 結點的度:圖中與結點相連的邊的數目
- 入度:在有向圖中,以這個結點為終點的有向邊的數目
- 出度:在有向圖中,以這個結點為起點的有向邊的數目
- 在無向圖中,如果兩點間存在路徑(不一定直接到達),則稱兩點連通
- 在有向圖中,如果兩點間可以互相到達,則稱兩點強聯通
- 一個無向圖,若每兩個點都連通,則稱此圖為連通圖
- 一個有向圖,若每兩個點都連通,則稱此圖為強連通圖
性質
- \(圖中所有結點的度的總和=邊數 \times 2\)
- 有向完全圖,共有\(n(n-1)\)條邊
- 無向完全圖,共有\(\frac{n(n-1)}{2}\)條邊
- \(n\)個點的連通圖,邊的數量至少為\(n-1\)
- \(n\)個點的強連通圖,邊的數量至少為\(n\)
演算法
排序
不穩定的排序:選擇、希爾、快排、堆排
- \(O(n^2)\):冒泡、選擇、插入、快排最壞
- \(O(n\log{n})\):歸併、快排、堆排、希爾、sort
- \(O(n)\):桶排、計數、基數
動態規劃
最大子段和
⚠️子段必須連續⚠️
\(dp_i\)代表以\(a_i\)為結尾的最大子段和
狀態轉移方程:\(dp_i=max({dp_{i-1}+a_i},{a_i})\)
最長上升子序列
⚠️子序列可以斷開⚠️
\(dp_i\)代表以\(a_i\)為結尾的最長上升子序列的長度
主要程式碼:
int ans=0;
for(int i=1;i<=n;i++){
dp[i]=1;
for(int j=1;j<i;j++){
if(a[j]<a[i]) dp[i]=max(dp[i],dp[j]+1);
}
ans=max(ans,dp[i]);
}
最長公共子序列
\(dp_{i,j}\)代表以\(s1_{i}\)為\(s1\)的末尾,\(s2_j\)為\(s2\)的末尾時的最長公共子序列長度
\[狀態轉移方程:dp_{i,j} = \begin{cases}
dp_{i-1,j-1}+1 &\text{if } s1_i=s2_j \\
max(dp_{i-1,j},dp_{i-1,j}) &\text{if } s1_i \ne s2_j
\end{cases}
\]
01揹包
\(f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i])\)
for(int i=1;i<=n;i++){
for(int j=m;j>=v[i];j--){
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
}
}
完全揹包
\(f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i])\)
for(int i=1;i<=n;i++){
for(int j=v[i];j<=m;j++){
dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
}
}
多重揹包
int cnt = 0;
for (int i = 1; i <= n; i ++ ){
int a, b, s;
int k = 1;
cin >> a >> b >> s;
while (k <= s){
cnt ++ ;
v[cnt] = a * k;
w[cnt] = b * k;
s -= k;
k *= 2;
}
if (s > 0){
cnt ++ ;
v[cnt] = a * s;
w[cnt] = b * s;
}
}//二進位制最佳化操作
n = cnt;
for (int i = 1; i <= n; i ++ )
for (int j = m; j >= v[i]; j -- )
f[j] = max(f[j], f[j - v[i]] + w[i]);