#0.0 前言
每次的CSP考試前最擔心的就是初賽,翻看了許多資料,還是覺得自己整理最有助於自己的理解,因而作此篇,望有助
#1.0 網絡常識
#1.1 網絡的分類
按地域范圍
- 局域網 范圍在一般在\(1km\)的范圍內,縮寫為\(LAN\)(Loacl Area Network)
- 城域網 范圍在幾千米到幾十千米以內,縮寫為\(MAN\)(Metorpolitan Area Network)
- 廣域網 范圍在幾十千米到幾千千米以上,縮寫為\(WAN\)(Wide Area Network)
注意:\(MAN\)和\(WAN\)一般都是由多個\(LAN\)構成的
按拓撲結構
- 星型 單個站點故障不會影響全網,依賴中央節點,連線費用大
- 總線型 總線本身的故障對系統是毀滅性的
- 環形 站點的故障會引起整個網絡的崩潰
- 網狀型(不規則形) 一般廣域網屬於不規則形,\(Internet\)網是當今世界規模最大、用戶最多、影響最廣泛的計算機互聯網絡
#1.2 網絡的體系結構
開放式系統互聯模型(英語:Open System Interconnection Model,縮寫:OSI;簡稱為OSI模型)是一種概念模型,由國際標准化組織(ISO)提出,一個試圖使各種計算機在世界范圍內互連為網絡的標准框架。
TCP/IP(Transmission Control Protocol/Internet Protocol,傳輸控制協議/網際協議)是指能夠在多個不同網絡間實現信息傳輸的協議簇。TCP/IP協議不僅僅指的是TCP 和IP兩個協議,而是指一個由FTP、SMTP、TCP、UDP、IP等協議構成的協議簇, 只是因為在TCP/IP協議中TCP協議和IP協議最具代表性,所以被稱為TCP/IP協議。
OSI模型與TCP/IT模型的對應關系
例題
NOIP 2012 普及組初賽試題第十題(限於篇幅,這里不展示原題)
#1.3 IP地址
IP地址是IP協議提供的一種統一的地址格式,它為互聯網上的每一個網絡和每一台主機分配一個邏輯地址,以此來屏蔽物理地址的差異。
該地址通常用由句點分隔的八位字節的十進制數表示,即4段二進制位組成,每組數字取值范圍只能是\(0 \sim 255\),如:
10000001 00001011 00000011 00011111
IP地址即為:129.11.3.31
IP地址分為A、B、C、D、E五類,如下圖
注意:主機ID所有域不能都為0或255,如網絡ID為10,那么就不能把10.0.0.0和10.255.255.255兩個IP地址分給任何主機;如網絡ID為192.114.31,那么就不能把192.114.31.0和192.114.31.255兩個IP地址分給任何主機
#2.0 數制轉換
為表達方便,常在數字后加一縮寫字母后綴作為不同進制數的標識
各進制的后綴字母:
- B:二進制數
- O:八進制數
- D:十進制
- H:十六進制
#2.1 十進制與二進制的互相轉換
二進制轉十進制
- 按權展開求和
如,
十進制整數轉二進制
- 除以2取余,逆序輸出
所以\((5)_{10}=(101)_2\)
十進制小數轉二進制
- 乘以2取余,順序輸出
所以\((0.625)_{10}=(0.101)_2\)
#2.2 八進制與二進制的互相轉換
八進制轉二進制
將每位八進制數轉化為3位二進制數,如\((37.416)_8\)
所以\((37.416)_8=(11111.10000111)_2\)
二進制轉八進制
將二進制數3位一組轉化為八進制數,整數部分位數不夠在前面加'\(0\)',小數部分位數不夠在后面加'\(0\)',如\((11111.10000111)_2\)
所以\((11111.10000111)_2=(37.416)_8\)
#2.3 十六進制與二進制的互相轉換
十六進制轉二進制
將每位十六進制數轉化為4位二進制數,如\((5DF.9)_{16}\)
所以\((5DF.9)_{16}=(10111011111.1001)_2\)
二進制轉十六進制
將二進制數4位一組轉化為十六進制數,整數部分位數不夠在前面加'\(0\)',小數部分位數不夠在后面加'\(0\)',如\((10111011111.1001)_2\)
所以\((10111011111.1001)_2=(5DF.9)_{16}\)
#2.4 十進制與八進制、十六進制的轉換
八進制轉十進制:\((\overline{a_0a_1a_2a_3...a_n})_8=(a_0 \cdot 8^n + a_1 \cdot 8^{n-1} + a_2 \cdot 8^{n-2} +...+ a_n \cdot 8^0)_{10}\)
如:\((36)_8=(3 \times 8^1 + 6 \times 8^0)_{10} = (24 + 6)_{10} = (30)_{10}\)
十六進制轉十進制:\((\overline{a_0a_1a_2a_3...a_n})_{16}=(a_0 \cdot 16^n + a_1 \cdot 16^{n-1} + a_2 \cdot 16^{n-2} +...+ a_n \cdot 16^0)_{10}\)
如:\((1E)_{16}=(1 \times 16^1 + 14 \times 16^0)_{10} = (16 + 14)_{10} = (30)_{10}\)
(其實與二進制轉十進制是一樣的)
十進制轉八進制和十六進制:與二進制一樣可使用短除法
#2.5 拓展 - 關於以上進制轉換的の思考
Q:為什么二進制按權展開求和得到的是對應的十進制?
設 \(b\) 是大於 \(1\) 正整數,則每個正整數 \(n\) 可唯一的表示成
其中 \(a_i\) 是整數, \(0 \leqslant a_{i} \leqslant b-1,i=1, \cdots ,k-1\),且首項系數 \(a_{k-1} \ne 0\)
證明:
運用歐幾里得除法,以得到所期望的表達式
首先,用 \(b\) 去除 \(n\) 得到
再用 \(b\) 去除不完全商 \(q_0\) 得到
繼續進行這種運算,依次得到
因為
所以必有整數 \(k\) 使得不完全商 \(q_{k-1}=0\)
這樣,依次得到
我們還需要證明這個表達式 \((1)\) 是唯一的,假設有兩種不同的表達式:
兩式相減得
假設 \(j\) 是最小的正整數使得 \(a_{j} \ne b_{j}\),則
或者
因此
故
但
又有 \(|a_{j}-c_{j}| < b\),沖突,也就是說 \(n\) 的表達式是唯一的
證畢.
由上面的證明我們可以得到,每個十進制正整數 \(n\) 可唯一的表示成
我們又知道任何進制中,每個數都可以按位權展開成各個數位上的數字乘以對應數位的位權再相加的形式,
以十進制為例,如:
\((3452)_{10} = (3 \times 10^3 + 4 \times 10^2 + 5 \times 10^1 + 2 \times 10^0)_{10}\)
那么,這里每一位所乘的數,為什么是 \(1000,100,10,1\) 而不是 \(8,4,2,1\) ?
很簡單,因為這是十進制,每一位滿十向下一位進一
看整數部分,第一位向第二位進一需要十,所以第二位上每一個 "\(1\)" 就有10,同理,第二位到第三位也需要十,就是 \(10 \times 10 = 10^2\),第三位到第四位也需要十,就是 \(10 \times 10 \times 10= 10^3\) ......
我們丟開十進制,看二進制:
二進制與十進制相似,只不過是滿二進一,所以很簡單可以得到,第一位向第二位進一需要二,所以第二位上每一個 "\(1\)" 就有2,同理,第二位到第三位也需要二,就是 \(2 \times 2 = 2^2\),第三位到第四位也需要二,就是 \(2 \times 2 \times 2= 2^3\) ......
而其他進制與此相同
所以可表示成 \((\overline{a_{k-1}a_{k-2}a_{k-3}a_{k-4} \cdots a_{0}})_b=(a_{k-1} \cdot b^{k-1} + a_{k-2} \cdot b^{k-2} + a_{k-3} \cdot b^{k-3} + \cdots + a_1 + a_0 \cdot b^0)_{10}\)
對應着一個唯一的十進制正整數 \(n\)
#2.6 例題
下列四個不同進制的數中,與其它三項數值上不相等的是
A. (269)16
B. (617)10
C. (1151)8
D. (1001101011)2
(269)16=(617)10
(617)10=(617)10
(1151)8=(617)10
(1001101011)2=(619)10
故選 D
#3.0 信息編碼
#3.1 儲存容量
比特(bit) 是指1位二進制的數碼(即0或1)。比特是計算機中表示信息的數據編碼中的最小單位
字節(Byte) 通常用8個二進制數字表示一個字節,即一個字節由8個比特組成,字節是儲存器系統最小的存取單位
儲存容量單位間換算
\(1KB=1024B\)
\(1MB=1024KB\)
\(1GB=1024MB\)
\(1TB=1024GB\)
例題
1MB 等於( )
A. 1000 字節
B. 1024 字節
C. 1000 * 1000 字節
D. 1024 * 1024 字節
1MB=1024KB 1KB=1024B
所以 1MB=1024 * 1024 B
選 D
一個32位整型變量占用()個字節。
A. 32
B. 128
C. 4
D. 8
一個字節有8位,即32/8=4個字節
選 C
#3.2 ASCII碼
記住 '\(a\)'為 \(97\) ,'\(A\)'為 \(65\) ,'\(0\)'為 \(48\)即可,其他都可以計算得到
#3.3 漢字信息編碼
漢字交換碼
由使用頻度分為一級漢字和二級漢字
字形儲存碼
一般用點陣儲存,在相同點陣中,不管其筆畫繁簡,所占字節數相同
#4.0 原碼·反碼·補碼
#4.1 原碼
原碼表示法是一種簡單的機器數表示法,即符號和數值表示法。
用二進制表示,最左邊的一位為符號位,剩下為數值位
符號位 '\(1\)' 表示負數,'\(0\)' 表示正數
- 正數的原碼就是他本身
- 負數的原碼符號位為 '\(1\)'
- \(0\) 有兩種表示方法,為 '\(+0(000...0)\)' 和 '\(-0(100...0)\)'
設 \(x\) 為真值,則 \([x]_原\) 為原碼
如,設 \(x=1100110\),則 \([x]_原=01100110\)
設 \(x=-1100110\),則 \([x]_原=11100110\)
原碼可表示的范圍(\(n\) 位二進制): \(0 \sim 2^n - 1\)(無符號),\(-(2^{n-1}-1) \sim 2^{n-1}-1\)(有符號)
如8位二進制,無符號表示范圍為 \(0 \sim 255\),有符號表示范圍為 \(-127 \sim 127\)
原碼不能直接參加運算,可能會出錯,如 \(1+(-1)=0\),而 \(00000001+10000001=10000010\),答案為 \(-2\),顯然錯誤
#4.2 反碼
反碼通常是用來由原碼求補碼或者由補碼求原碼的過渡碼
- 當原碼為正數時,反碼與原碼一致
- 當原碼為負數時,反碼是原碼除符號位外,其他位按位取反。
- \(0\) 有兩種表示方法,為 '\(+0(000...0)\)' 和 '\(-0(111...1)\)'
設 \(x\) 為真值,則 \([x]_反\) 為反碼
如,設 \(x=1100110\),則 \([x]_反=01100110\)
設 \(x=-1100110\),則 \([x]_反=10011001\)
反碼可表示的范圍(\(n\) 位二進制): \(-(2^{n-1}-1) \sim 2^{n-1}-1\)(不存在無符號情況)
如8位二進制,表示范圍為 \(-127 \sim 127\)
#4.3 補碼
在計算機系統中,數值一律用補碼來表示和存儲。原因在於,使用補碼,可以將符號位和數值域統一處理;同時,加法和減法也可以統一處理
- 當原碼為正數時,補碼與原碼一致
- 當原碼為負數時,補碼是反碼加一。
- \(0\) 只有一種表示方法,\([+0]_補=[-0]_補=000...0\)
設 \(x\) 為真值,則 \([x]_補\) 為補碼
如,設 \(x=1100110\),則 \([x]_補=01100110\)
設 \(x=-1100110\),則 \([x]_補=10011010\)
補碼可表示的范圍(\(n\) 位二進制): \(-2^{n-1} \sim 2^{n-1}-1\)(不存在無符號情況)
如8位二進制,表示范圍為 \(-128 \sim 127\)(\(10000000\) 的值為 \(-128\),\(11111111\) 的值為 \(-1\))
#4.4 關於補碼加法和減法也可以統一處理的解釋
先介紹一下“模”的概念:“模”是指一個計量系統的計數范圍,如過去計量糧食用的斗、時鍾等。計算機也可以看成一個計量機器,因為計算機的字長是定長的,即存儲和處理的位數是有限的,因此它也有一個計量范圍,即都存在一個“模”。如:時鍾的計量范圍是 \(0 \sim 11\),模= \(12\)。表示n位的計算機計量范圍是 \(0 \sim 2^n -1\),模= \(2^n\).“模”實質上是計量器產生“溢出”的量,它的值在計量器上表示不出來,計量器上只能表示出模的余數。任何有模的計量器,均可化減法為加法運算。就是取反后加1。
——摘自補碼_百度百科
假設當前時針指向8點,而准確時間是6點,調整時間可有以下兩種撥法:
- 一種是倒撥2小時,即 \(8-2=6\)
- 一種是順撥10小時,\(8+10=12+6=6\),即 \(8-2=8+10=8+12-2 (\mod 12)\)
在12為模的系統里,加10和減2效果是一樣的,因此凡是減2運算,都可以用加10來代替。若用一般公式可表示為:\(a-b=a-b+mod=a+(mod-b)\)。對“模”而言,2和10互為補數。實際上,以12為模的系統中,11和1,8和4,9和3,7和5,6和6都有這個特性,共同的特點是兩者相加等於模。對於計算機,其概念和方法完全一樣。n位計算機,設n=8,所能表示的最大數是 \(11111111\),若再加1成 \(100000000\)(9位),但因只有8位,最高位1自然丟失。又回到了 \(00000000\),所以8位二進制系統的模為 \(2^8\)。在這樣的系統中減法問題也可以化成加法問題,只需把減數用相應的補數表示就可以了。把補數用到計算機對數的處理上,就是補碼
#4.5 補碼求原碼
已知一個數的補碼,求原碼的操作其實就是對該補碼再求補碼:
- 如果補碼的符號位為“0”,表示是一個正數,其原碼就是補碼。
- 如果補碼的符號位為“1”,表示是一個負數,那么求給定的這個補碼的補碼就是要求的原碼。
例:已知一個補碼為 \(11111001\),則原碼是 \(00000111(-7)\)。
因為符號位為“1”,表示是一個負數,所以該位不變,仍為“1”。
其余七位 \(1111001\) 取反后為 \(0000110\);再加1,所以是 \(00000111\)。
#4.6 例題
在 8 位二進制補碼中,10101011 表示的數是十進制下的( )。
A. 43
B. -85
C. -43
D. -84
先將補碼轉換為原碼,已知補碼求原碼,就是將這個補碼再求補碼
而符號位為1,說明為負數,則除符號位外,按位取反,再加一
得:11010101
轉化為十進制為 -85
故選 B
#5.0 邏輯運算
注:這里講的是數學布爾運算
邏輯運算符:
- \(\lnot\) (邏輯非)
- \(\land\) (邏輯與)
- \(\lor\) (邏輯或)
- \(1\) 和 \(0\) 表示 “真” 和 “假”
#5.1 運算級比較
\(\lnot(非) > \land(與) > \lor(或)\)
若有括號先算括號內的,同級運算由左向右
#5.2 運算規則
- \(\lnot\) 之后的若為真,則為假;若為假,則為真。簡單來講,就是取反
- \(\land\) 左右兩者都為真,則為真,否則為假
- \(\lor\) 左右兩者有一者及以上為真,則為真,否則為假
#6.0 位運算
程序中的所有數在計算機內存中都是以二進制的形式儲存的。位運算就是直接對整數在內存中的二進制位進行操作。
位運算符
- \(\& (and)\) (按位與)
- \(|(or)\) (按位或)
- \(\hat{} (xor)\) (按位異或)
#6.1 運算級比較
\(\& (與) > \hat{} (異或) > |(或)\)
若有括號先算括號內的,同級運算由左向右
#6.2 運算規則
注:以下運算規則都是將數字轉為二進制后對於每一位的運算
- \(\&\) 兩者都為 \(1\),則為 \(1\),否則為 \(0\)
- \(\hat{}\) 兩者不同(一 \(1\) 一 \(0\)),則為 \(1\),否則為 \(0\)
- \(|\) 兩者有一者及以上為 \(1\),則為 \(1\),否則為 \(0\)
例:
所以 \(22 \& 5=4\)
所以 \(22 \hat{} 4=18\)
所以 \(22 | 5=23\)
#7.0 數據結構
#7.1 棧
棧(stack)又名堆棧,它是一種運算受限的線性表。限定僅在表尾進行插入和刪除操作的線性表。這一端被稱為棧頂,相對地,把另一端稱為棧底。向一個棧插入新元素又稱作進棧、入棧或壓棧,它是把新元素放到棧頂元素的上面,使之成為新的棧頂元素;從一個棧刪除元素又稱作出棧或退棧,它是把棧頂元素刪除掉,使其相鄰的元素成為新的棧頂元素。
棧的特點:后入先出
#7.2 隊列
隊列的特點:先入先出
#7.3 二叉樹
性質
- 在二叉樹的第 \(i\) 層上最多有 \(2^{i-1}\) 個節點(\(i \geqslant 1\))
- 深度為 \(k\) 的二叉樹至多有 \(2^k-1\) 個節點(\(k \geqslant 1\))
- 對任意一棵二叉樹,如果其葉節點數為 \(n_0\) ,度為 \(2\) 的節點數為 \(n_2\) ,則一定滿足:\(n_0 = n_2 + 1\)
- 具有 \(n\) 個節點的完全二叉樹的深度為 \(\lfloor \log_{2}n \rfloor + 1\)
- 對於一棵 \(n\) 個節點的完全二叉樹,對任意一個節點(編號為 \(i\)),有:
- 如果 \(i=1\),則節點 \(i\) 為根,無父節點
- 如果 \(i>1\),則其父結點編號為 \(\dfrac{i}{2}\),
- 如果 \(2 \times i > n\),則結點 \(i\) 無左右兒子,為葉結點,否則左兒子編號為 \(2 \times i\)
- 如果 \(2 \times i + 1 > n\),則結點 \(i\) 無右兒子,否則右兒子編號為 \(2 \times i + 1\)
#7.4 線段樹
本人曾寫過一篇講線段樹的文章,這里便不再贅述,有興趣的可以點擊下方傳送門進入
#8.0 數學問題
推銷大佬博客(自己懶)
#9.0 其他
#9.1 圖片大小計算
公式
\(圖片大小=\dfrac{分辨率(長 \times 寬) \times 位深}{8}\)
例題
如有一張分辨率為 \(4096 \times 2160\) ,每一像素都是 \(24\) 位真彩色,則圖片大小大約是:
A. 8MB
B. 25MB
C. 200MB
D. 200KB
這張圖片的大小為:
選 B
#9.2 哈夫曼編碼
哈夫曼編碼(Huffman Coding),又稱霍夫曼編碼,是一種編碼方式,哈夫曼編碼是可變字長編碼(VLC)的一種。Huffman於1952年提出一種編碼方法,該方法完全依據字符出現概率來構造異字頭的平均長度最短的碼字,有時稱之為最佳編碼,一般就叫做Huffman編碼(有時也稱為霍夫曼編碼)。 ——百度百科·哈夫曼編碼
比如說,我們有 \(4\) 種字符,分別為 \(a\),\(b\),\(c\),\(d\),分別出現的次數是 \(20\) 次,\(50\) 次,\(5\) 次,\(25\) 次
構建哈夫曼編碼時先計算每個字符出現的概率,得到:
\(P(a)=\dfrac{1}{5}\)
\(P(b)=\dfrac{1}{2}\)
\(P(c)=\dfrac{1}{20}\)
\(P(d)=\dfrac{1}{4}\)
然后按照大小進行排序
然后取概率最小的兩個符號開始,可選其中一個支路為0,另一支路為1。這里,我們選上支路為0,下支路為1。將兩支路的概率合並,並重新排隊
依次類推,概率並為1,最終可得下圖
從概率1到單個字符的概率的路徑上的0或1組合就成了該字符的編碼
更新日志及說明
更新
- 初次完成編輯 - \(2020.10.8\)
- 修改了 #2.4 十進制與八進制和十六進制的轉換 的部分錯誤,感謝 zythonc指出 - \(2020.10.9\)
- 增添了 #9.2 哈夫曼編碼
修改了部分符號錯誤 - \(2020.10.11\)
本文若有更改或補充會持續更新