# CSP-S 初賽問題求解與選擇題
## 時間復雜度計算
公式:對於 $T(n) = a \times T(\dfrac{n}{b})+O(n^d)$ 這個遞推式,其時間復雜度為:
$$
T(n) =
\begin{cases}
O(n^{\log_b a}) , \ a > b^d \\
\\
O(n^d \lg n) , \ a = b^d \\
\\
O(n^d) , \ a<b^d
\end{cases}
$$
## 鴿巢原理
### 基本定義
若有 $n$ 個鴿巢,$n+1$ 只鴿子,則至少有一個鴿巢里至少有兩只鴿子。
變形:
1. 一年 $365$ 天,今有 $366$ 個人,則其中至少有兩個人生日相同。
2. 抽屜里有 $10$ 雙手套,從中取 $11$ 只出來,其中至少有兩只是完整配對的。
### 經典例題
1. ($NOIP \ 2012$ )如果平面上任取 $n$ 個整點(橫縱坐標都是整數),其中一定存在 $2$ 個點,它們連線的中點也是整點,那么 $n$ 至少是( )。
**解:**存在 $2$ 個點中點是整點,要求兩點橫縱坐標奇偶性都相同。根據鴿巢原理,$n$ 至少是 $2 \times 2+1=5$
2. 在邊長為 $1$ 的正方形內任取 $5$ 點,則其中至少有 $2$ 點的距離不超過( )。
**解:**如下圖所示,將一個正方形分成四份,那么至少有 $2$ 個點在同一個小正方形里面。在同一個正方形里面的兩點最長距離即為 $\dfrac{\sqrt{2}}{2}$ 。

3. 證明:一位國際象棋大師有 $11$ 周的時間備戰比賽,他決定每天至少下 $1$ 盤棋,但每周不超過 $12$ 盤。則存在連續若干天,他恰好下了 $21$ 盤棋。
**解:**令 $a_i$ 為到第 $i$ 天下的總盤數,那我們要證明存在 $i,j$ 滿足 $a_i+21=a_j$ 。
$\because$ 他每天至少下 $1$ 盤棋
$\therefore$ $a_i$ 是單調遞增的
$\therefore$ $1 < a_1 < a_2 < \ldots < a_{77} < 11 \times 12=132$
$\therefore$ $22 < a_1+21 < a_2+21 < \ldots < a_{77}+21 < 132+21=153$
上下兩式總共有 $153$ 種取值,卻有 $154$ 個數,所以存在 $i < j$ 滿足 $a_i+21=a_j$。
### 加強形勢
現有鴿巢 $n$ 個,鴿子 $m_1+m_2+ \cdots +m_n-n+1$ 只,其中 $m_1,m_2, \ldots ,m_n, n \in \N^*$
**結論:**鴿巢 $1$ 鴿子數 $> m_1$,或鴿巢 $2$ 鴿子數 $> m_2$,…… 或鴿巢 $n$ 鴿子數 $> m_n$,至少有一個成立。
### 擴展內容:Erdös-Szekeres 定理
在由 $n^2+1$ 個實數構成的序列中,必然含有長為 $n+1$ 的單調(增或減)子序列。
## Ramsey 問題
命題:$6$ 人中或者至少存在 $3$ 人互相認識,或者至少存在 $3$ 人互相不認識。
等價問題:六個頂點的完全圖的邊,用紅、藍二色任意着色,則至少存在一紅色邊三角形,或一藍色邊三角形。
## 排列組合
### 前置知識
$A_n^n = n! $
$A_n^m = n(n-1)(n-2) \cdots (n-m+1) = \dfrac{n!}{(n-m)!}$
$C_n^m = \dfrac{A_n^m}{A_m^m} = \dfrac{n(n-1)(n-2) \cdots (n-m+1)}{m!} = \dfrac{n!}{m!(n-m)!} $
另外,規定 $C_n^0 = 1$
圓排列(在一個圓里,經旋轉后相同算同一種解):$Q_n^r = \dfrac{A_n^r}{r} = \dfrac{n!}{r \cdot (n-r)!}$
### 重要定理及證明
1. $\ C_n^m = C_n^{n-m}$
我們可以這么想:組合就是從 $n$ 個元素中隨機抽出 $m$ 個元素,那這樣和從 $n$ 個元素中抽出 $n-m$ 個元素保留不是一個道理嗎?所以就有了這個公式:$\ C_n^m = C_n^{n-m}$
2. $C_{n+1}^m = C_n^m + C_n^{m-1}$ **【記牢,經常用!!!】**
> 方法1:我們可以這么想:假設集合 $A$ 中現在有 $n+1$ 個元素,分別為 $a_1,a_2,\cdots,a_{n+1}$ ,那么從集合 $A$ 中抽出 $m$ 個元素,就可以分類討論:如果抽出的元素中不含有 $a_1$ ,那么就是從 $n$ 個元素中抽出 $m$ 個元素,一共有 $C_n^m$ 種;如果抽出的元素中含有 $a_1$,那么就有 $C_n^{m-1}$ 種方法。所以 $C_{n+1}^m = C_n^m + C_n^{m-1}$。
>
> 方法2:階乘證明:
>
> $\because$ 左邊 $=$ $\dfrac{(n+1)!}{m!(n+1-m)!}$
>
> $\because$ 右邊 $= $ $\dfrac{n!}{m!(n-m)!} + \dfrac{n!}{(m-1)!(n+1-m)!} = \dfrac{n!(n-m+1)}{m!(n+1-m)!} + \dfrac{n! \cdot m}{m!(n+1-m)!} = \dfrac{(n+1)!}{m!(n+1-m)!}$
>
> $\therefore$ 左邊 $=$ 右邊
>
> $\therefore \ C_{n+1}^m = C_n^m + C_n^{m-1}$
>
> 方法3:楊輝三角形的任意一個數都等於它肩上的兩個數之和,再結合二項式定理,就可以得出這個規律。
3. $C_n^m = \dfrac{m+1}{n+1} C_{n+1}^{m+1}$
同樣,這里也可以用階乘來證明:
$\because$ 左邊 $=$ $\dfrac{n!}{m!(n-m)!} $
$\because$ 右邊 $=$ $\dfrac{m+1}{n+1} \cdot \dfrac{(n+1)!}{(m+1)!(n+1-m-1)!} = \dfrac{m+1}{n+1} \cdot \dfrac{(n+1)!}{(m+1)!(n-m)!} = \dfrac{m+1}{n+1} \cdot \dfrac{n! (n+1)}{m!(n-m)!(m+1)} = \dfrac{n!}{m!(n-m)!}$
$\therefore$ 左邊 $=$ 右邊
$\therefore$ $C_n^m = \dfrac{m+1}{n+1} C_{n+1}^{m+1}$
4. 一個含有 $n \ (n \in N^*)$ 個元素的集合 $A = \{ a_1,a_2,\cdots , a_n \}$,不同的子集又 $2^n$ 個。
### 二項式定理
1. 俗話來說,就是**楊輝三角形**!
2. 二項式定理公式:
$$
\large (a+b)^n = C_n^0a^n + C_n^1a^{n-1}b^1 + \cdots + C_n^ka^{n-k}b^k + \cdots +C_n^nb^n (n \in N^*)
$$
3. 二項式定理通項:
$$
\large T_{k+1} = C_n^ka^{n-k}b^k
$$
4. 二項式系數之和:
令 $(a+b)^n = C_n^0a^n + C_n^1a^{n-1}b^1 + \cdots + C_n^ka^{n-k}b^k + \cdots +C_n^nb^n (n \in N^*)$,那么 $C_n^0 + C_n^1 + \cdots + C_n^n = 2^n$
> 證明:
>
> 用賦值法,令 $a = b = 1$,那么 $(a+b)^n = C_n^0 + C_n^1 + \cdots + C_n^n = (1+1)^n = 2^n$
5. 二項式系數最值問題:
都知道楊輝三角形其實是一個十分對稱的三角形,每一行的最大值就是在這一行最中間的那個數。對於 $(a+b)^n$,展開后只要關注$\dfrac{n}{2}$ 的值。如果 $\dfrac{n}{2}$ 的值是整數,那么二項式系數的最大值就是 $C_n^{\frac{n}{2}}$ ;反之,如果 $\dfrac{n}{2}$ 是小數,那么二項式系數的最大值就是 $C_n^{[\frac{n}{2}]} , C_n^{[\frac{n}{2}]+1}$ ( $[x]$ 表示對 $x$ 向下取整)。
### 錯位排列
問題:有 $n$ 個信封和 $n$ 個信箱,分別編號為 $1$ 到 $n$,相同編號的信封和信箱不能放一起,則有幾種方法?
公式:$f(n)=(n-1)(f(n-1)+f(n-2))$
錯位排列的前幾項:$0,1,2,9,44,265$
**並不是所有的問題都適用排列組合,視情況而定!**
## 卡特蘭數
### 公式
先看這個問題:在 $n \times n$ 的網格里從左下角走到右上角的不經過 $y = x$ 這條線的單調路徑的條數。

路徑條數即為:$\dbinom{n}{2n} - \dbinom{n-1}{2n} = \dfrac{1}{n+1} \dbinom{n}{2n}$
卡特蘭數通式即為:$C_n = \dbinom{n}{2n} - \dbinom{n-1}{2n} = \dfrac{1}{n+1} \dbinom{n}{2n}$
卡特蘭數的遞推公式 $1$:$C_n = C_0 \times C_{n-1} + C_1 \times C_{n-2} + \cdots + C_{n-1} \times C_0,C_0 = 1$
卡特蘭數的遞推公式 $2$:$C_n = \dfrac{C_{n-1} \times (4 \times n - 2)}{n+1}$
### 應用
1. 求帶限制條件的路徑條數
2. 求合法的括號序列的個數
3. 求出棧次序
4. 買票找票問題:有 $2n$ 個人排成一行進入劇場。入場費 $5$ 元。其中只有 $n$ 個人有一張 $5$ 元鈔票,另外 $n$ 人只有 $10$ 元鈔票,劇院無其它鈔票,問有多少種方法使得只要有 $10$ 元的人買票,售票處就有 $5$ 元的鈔票找零?(將持 $5$ 元者到達視作將 $5$ 元入棧,持 $10$ 元者到達視作使棧中某 $5$ 元出棧)
5. 排隊問題:現在有 $2n$ 個人,他們身高互不相同,他們要成兩排,每一排有 $n$ 個人,並且滿足每一排必須是從矮到高,且后一排的人要比前一排對應的人要高,問有多少種方案。
6. 凸多邊形三角划分:在一個凸多邊形中,通過若干條互不相交的對角線,把這個多邊形划分成了若干個三角形。任務是輸入凸多邊形的邊數 $n$,求不同划分的方案數 $f(n)$。
7. 給定節點構成二叉搜索樹
## 指針問題
### 指針定義
C語言里,變量存放在內存中,而內存其實就是一組有序字節組成的數組,每個字節有唯一的內存地址。CPU 通過內存尋址對存儲在內存中的某個指定數據對象的地址進行定位。這里,數據對象是指存儲在內存中的一個指定數據類型的數值或字符串,它們都有一個自己的地址,而指針便是保存這個地址的變量。也就是說:**指針是一種保存變量地址的變量**。
### 如何定義一個指針
指針其實就是一個變量,指針的聲明方式與一般的變量聲明方式沒太大區別,下面舉了幾個栗子:
```cpp
int *p; // 聲明一個 int 類型的指針 p
char *p // 聲明一個 char 類型的指針 p
int *arr[10] // 聲明一個指針數組,該數組有10個元素,其中每個元素都是一個指向 int 類型對象的指針
int (*arr)[10] // 聲明一個數組指針,該指針指向一個 int 類型的一維數組
int **p; // 聲明一個指針 p ,該指針指向一個 int 類型的指針
```
聲明一個指針變量並不會自動分配任何內存。在對指針進行間接訪問之前,指針必須進行初始化:或是使他指向現有的內存,或者給他動態分配內存,否則我們並不知道指針指向哪兒。同時,對指針進行初始化后,便可以正常對指針進行賦值了。 初始化的操作如下:
```cpp
/* 方法:使指針指向現有的內存 */
int x = 1;
int *p = &x; // 指針 p 被初始化,指向變量 x ,其中取地址符 & 用於產生操作數內存地址
```
就如下面這個程序,輸出為:`1 2`
```cpp
#include <bits/stdc++.h>
int main(){
int x = 1;
int *p = &x;
printf("%d ",*p);
*p = 2;
printf("%d\n",*p);
return 0;
}
```
### NULL指針
NULL 指針是一個特殊的**指針變量**,表示不指向任何東西。可以通過給一個指針賦一個零值來生成一個 NULL 指針。
### 指針的運算
1. 指針 $+/-$ 整數
可以對指針變量 $p$ 進行 `p++`、`p--`、`p+i` 等操作,所得結果也是一個指針,只是指針所指向的內存地址相比於 $p$ 所指的內存地址前進或者后退了 $i$ 個操作數。
2. 指針 $-$ 指針
只有當兩個指針都指向同一個數組中的元素時,才允許從一個指針減去另一個指針。減法運算的值是兩個指針在內存中的距離(以數組元素的長度為單位),因為減法運算的結果將除以數組元素類型的長度。舉個例子:
```cpp
#include "stdio.h"
int main(){
int a[10] = {1,2,3,4,5,6,7,8,9,0};
int sub;
int *p1 = &a[2];
int *p2 = &a[8];
sub = p2-p1;
printf("%d\n",sub); // 輸出結果為 6
return 0;
}
```
## 邏輯運算
1. 概念:非:not $ ¬$ 與:and $∧$ 或:or $∨$ 異或:xor $⊕$
2. 運算符的優先級:

## OI歷史及規則
### 各項賽事
1. `NOI` 全國青少年信息學奧林匹克競賽,從 $1984$ 年開始至今
2. `NOIP` 全國青少年信息學奧林匹克聯賽,從 $1995$ 年到 $2018$ 年~~(NOIP已死)~~
3. `CSP認證` 從 $2014$ 年開始
4. `CSP-J/S` 非專業級別的能力認證,從 $2019$ 年開始
5. `APIO` 亞洲與太平洋地區信息學奧賽,從 $2007$ 年開始,第一屆在澳大利亞舉行
6. `IOI` 國際信息學奧林匹克競賽,從 $1989$ 年在保加利亞開始。中國承辦 `IOI` $2000$
### 聯賽規則
不用說了,自己訪問 www.noi.cn 去看吧!
## 計算機基礎知識
### 發展史
1. $1946$ 年 $2$ 月,在美國賓夕法尼亞大學誕生了世界上第一台電子計算機`ENIAC`,這台計算機占地 $170$ 平方米,重 $30$ 噸,用了 $18000$ 多個電子管,每秒能進行 $5000$ 次加法運算。
2. 計算機的 $4$ 個發展過程:
>$1.$ 電子管 $1946 - 1958$
>
>$2.$ 晶體管 $1959-1964$
>
>$3.$ 集成電路 $1965-1970$
>
>$4.$ 大規模,超大規模集成電路 $1971 - Now$
3. 馮·諾依曼(美籍匈牙利數學家)思想:計算機由存儲器,控制器,運算器,輸入設備,輸出設備 $5$ 部分組成。
4. 圖靈:英國數學家,$1912-1954$
### 系統的基本結構和常識

2. CPU(中央處理器)的主要指標為主頻和字長。
3. CPU是微機的核心部件,是決定微機性能的關鍵部件。$20$ 世紀 $70$ 年代微型機的CPU問世,微型計算機的核心部件微處理器從`Intel 4004`,`80286`,`80386`,`80486` 發展到 `Pentium II/III` 和 `Pentium 4`,數位從$4$ 位、$8$ 位、$16$ 位、$32$ 位發展到 $64$ 位,主頻從幾 $MHZ$ 到今天的數 $GHZ$ 以上($1GHZ=1000MHZ$),CPU芯片里集成的晶體管數由 $2$ 萬個躍升到 $1000$ 萬個以上。
4. 世界上第一個CPU:`Inter 4004`。
5. 進制轉換:$1TB=1024GB=1024^2MB=1024^3KB=1024^4B$
6. 各種存儲器讀取速度比較:`Cache` $>$ `RAM` $>$ `ROM` $>$ 外存 **離CPU越近,速度越快**
7. 總線結構可分為:數據,地址,控制總線。
8. 計算機的軟件:

9. 計算機的語言:機器語言,匯編語言,高級語言
10. 在高級語言中,編譯性語言有 `C/C++`、`Pascal/Object Pascal(Delphi)`等;解釋性語言有 `ASP`、`PHP`、`Java`、`JavaScript`、`VBScript`、`Perl`、`Python`、`Ruby` 等。
### 信息編碼
1. 字節是存儲器系統的最小存取單位。
2. 英文編碼:$ASCII$ 碼。$ASCII$ 編碼是由美國國家標准委員會制定的一種包括數字、字母、通用符號和控制符號在內的字符編碼集,全稱叫美國國家信息交換標准代碼(American Standard Code for Information Interchange)。

3. 漢字編碼:國家標准 $GB2312$:包括了 $6763$ 個漢字。
### 原碼,反碼,補碼
1. 原碼:原碼就是符號位加上真值的絕對值,即用第一位($+ = 0,-=1$)表示符號,其余位表示值。
>$+1 = 0000 0001, -1=1000 0001$
2. 反碼:正數的反碼是其本身,負數的反碼是在其原碼的基礎上,符號位不變,其余各個位取反。
>$+1 = [0000 0001]_原 = [0000 0001]_反$
>
>$-1 = [1000 0001]_原 = [1111 1110]_反$
3. 正數的補碼就是其本身,負數的補碼是在其原碼的基礎上,符號位不變,其余各位取反,最后 $+1$。(即在反碼的基礎上 $+1$)
>$+1 = [0000 0001]_原 = [0000 0001]_反 = [0000 0001]_補$
>
>$-1 = [1000 0001]_原 = [1111 1110]_反 = [1111 1111]_補$
# CSP-S 初賽閱讀程序與程序填空
## 閱讀程序與程序填空
### 常考算法
>約瑟夫環、幻方、求逆序對、歸並排序相關操作、求逆序對、快速冪、組合數學、楊輝三角、二進制、搜索(遍歷)、$\gcd$ 、$ex\gcd$、最長上升子序列、最長公共子序列、最長公共上升子序列、康拓展開……
其實主要還是以做題為主(模板題)。

推薦書籍:《算法競賽進階指南》
推薦網站:[牛客網](https://ac.nowcoder.com/acm/skill/noip-tg)