CSP第一轮测试复习资料整合

给大伙表演一个原地退役。

信息学历史

计算机组成

字长:$32$ 位和 $64$ 位。

主频:$2.4\text{GHz}$ 。

内存:$8\text{GB}$ 。

位($\text{Bit}$):一个 $01$ 。

字节($\text{Byte}$):八个 $01$ 。

内存换算

$\text{1KB=1024Byte}$

$\text{1MB=1024KB}$

$\text{1GB=1024MB}$

$\text{1TB=1024GB}$

摩尔定律

$18$ 个月翻倍。其核心内容为:集成电路上可以容纳的晶体管数目在大约每经过 $18$ 个月到 $24$ 个月便会增加一倍。换言之,处理器的性能大约每两年翻一倍,同时价格下降为之前的一半。

软件系统

操作系统:$\text{Windows,DOS,UNIX,Linux,MaxOS,Android,iOS,}$ 鸿蒙(华为)。

应用软件:浏览器,办公软件,游戏等。

软件由机器语言,汇编语言,高级语言编写。

编码

文字,图片,声音等都会转化成 $01$ 串编码。

编码有:$\text{ASCII}$ 码,$\text{GBK}$ 码($\text{2 byte}$),$\text{utf-8}$ 码($\text{3 byte}$ )等。

图片文件格式:$\text{jpg,png,jpeg,tiff,raw,bmp,gif}$ 等。

视频文件格式:$\text{wmv,mp4,m4v,avi,flv,mkv,dat}$ 等。

声音文件格式:$\text{wav,mp3,midi,wma,cda}$ 等。

NOI 系列

$\text{NOI}$ 开始于 $1984$ ,由中国计算机学会($\text{CCF}$)举办。

$\text{NOIp}$ 生于 $1995$ ,死于 $2019$ ,复活于 $2020$ 。

在 $2022$ 后,$\text{NOI}$ 仅支持 C++

考场仅能携带文具(无纸张),衣物,证件。

程序设计

所谓编译,就是把代码变成可执行文件(机器码),使用 C++Pascal 等媒介。

解释性语言指的是一行一行的运行,如 PythonJavaScriptPHPBASIC

两者的区别在于,编译不允许局部错误,解释允许局部错误。

时间复杂度:数据规模增长和运行时间增长的趋势。

算法

排序

排序中的稳定指的是对于相同的数而言,其相对排名在排序后不变,则称为稳定。

计数排序

不基于比较,时间复杂度 $\mathcal O(a+n)$ ,仅能求出最大值。

$a$ 是选票数,$n$ 是候选人数。


选择排序

不稳定,时间复杂度 $\mathcal O(n^2)$ 。


冒泡排序

稳定,时间复杂度 $\mathcal O(n^2)$ 。


插入排序

稳定,时间复杂度 $\mathcal O(n^2)$ 。


归并排序

稳定,时间复杂度 $\mathcal O(n\log n)$ ,需要额外辅助空间。


快速排序

不稳定,$\Omega(n\log n)-\mathcal O(n^2)$ 。


堆排序

不稳定,时间复杂度 $\mathcal O(n\log n)$ 。


贪心

需要证明的可能不正确算法。


二分

在有序中折半查找,时间复杂度 $\mathcal O(\lceil\log_2 n\rceil)$ 。


递推递归

递推是从小到大顺推

递归是从大到小逆推后反推回去

使用示例:斐波那契,杨辉三角,动态规划等。


分治

大问题拆成小问题,递归解决。

归并排序和快速排序都用到了分治策略。


主定理

有一种奇妙的东西叫做主定理,(另话:关于时间复杂度的计算,$\text{Sukwants}$ 写了三篇较详细的文章,可以去看看)可以计算递归式的时间复杂度,形如:

有一个奇妙的公式,和做法,可以硬背。


这里的 $T(n)$ 是时间复杂度函数


首先表明定义:

  • $n$ 为求得序列的第几位,称为问题规模大小;
  • $a$ 为原问题的子问题个数;
  • $\frac{n}{b}$ 为子问题大小,这里假设每个子问题大小相同;
  • $f(n)$ 为合并代价,即合并时间。

用通俗的话来讲:首先考虑 $aT(\frac{n}{b})$ 的时间,有公式 $\mathcal O(\log_ba\times n)$ ,然后考虑 $f(n)$ 的时间复杂度(假设为 $\mathcal O(t)$),这里分为三种情况:

  1. 如果 $\mathcal O(n^{\log_ba})>\mathcal O(t)$ ,则 $T(n)=\mathcal O(n^{\log_ba})$ ;
  2. 如果 $\mathcal O(n^{\log_ba})<\mathcal O(t)$ ,则 $T(n)=\mathcal O(t)$ ;
  3. 如果 $\mathcal O(n^{\log_ba})=\mathcal O(t)$ ,则 $T(n)=\mathcal O(n\log t)=\mathcal O(n\log\log_ba)$。

严格而言,上述三种情况其实是:

  1. 若函数 $n^{\log_ba}$ 更大,则 $T(n)=\Theta(n^{\log_ba})$ ;
  2. 若函数 $f(n)$ 更大,且满足 $af(\frac{n}{b})\leq cf(n)$ ,则 $T(n)=\Theta(f(n))$ ;
  3. 若两函数相等,则 $T(n)=\Theta(n^{\log_ba}\log^{k+1}n)$ 。

我也不知道为什么,背就完了。

举几个例子,可能就有所理解了。

二分:$T(n)=T(\frac{n}{2})+\Theta(1)$

得到 $a=1,b=2,f(n)=1$ ,则 $\mathcal O(n^{\log_ba})=0=\Theta(1)$ ,则时间复杂度为 $\mathcal O(\log n)$ 。

归并:$T(n)=2T(\frac{n}{2})+\Theta(n)$

得到 $a=2,b=2,f(n)=n$ ,则 $\mathcal O(n^{\log_ba})=n=\Theta(n)$ ,则时间复杂度为 $\mathcal O(n\log n)$ 。

二叉树遍历:$T(n)=2T(\frac{n}{2})+\mathcal O(1)$

得到 $a=2,b=2,f(n)=1$ ,则 $\mathcal O(n^{\log_ba})=n>1=\mathcal O(n)$ ,则时间复杂度为 $\mathcal O(n)$ 。


需要注意的是,$\log n$ 并不属于多项式范畴,所以严格来讲,$\mathcal O(n\log n)$ 和 $\mathcal O(n)$ 是同级的,所以,对于下面的式子:

$T(n)=2T(\frac{n}{2})+n\log n$

有 $n^{\log _ba=1}=n$ 和 $f(n)=n\log n$ ,两者同级,所以时间复杂度为 $\mathcal O(n\log^2 n)$ 。


数据结构

处理数据的骨架。

线性表

$\text{FILO}$ 式数据结构。($\text{First Input ,Last Output}$ ,先进后出)

常用于深度优先搜索($\text{dfs}$)。


队列

$\text{FIFO}$ 式数据结构。($\text{First Input ,First Output}$ ,先进先出)

常用于宽度优先搜索($\text{bfs}$,也称作广度优先搜索)


链表

每一个数都只有一个指针指向自己的下一位,从何由指针组成一条完整的链。

插入删除不需要移动元素,不许事先估计存储空间,所需空间与线性表长度成正比,但不支持随机访问。(因为内存不连续)


$n$ 个结点,$n-1$ 条边,所有结点连通且没有环的图。

森林:树的集合。

二叉树

每一个结点至多有 $2$ 个子结点的有根树。

一棵深度为 $i$ 的二叉树每一层数量至多为 $2^{i-1}$ ,一共结点至多为 $2^i-1$ 。

满(完美)二叉树(结点为 $2^i-1$ 的二叉树),完全二叉树为 $i-1$ 层都满的二叉树,完全线段树就是一种完全二叉树。

二叉树有 $3$ 种遍历方式:前序遍历,中序遍历,后序遍历。

前序遍历:根结点 $\to$ 左子树 $\to$ 右子树。

中序遍历:左子树 $\to$ 根结点 $\to$ 右子树。

后序遍历:左子树 $\to$ 右子树 $\to$ 根结点。

其中,前序遍历扩展到普通树型结构,并区分轻重儿子,就是树链剖分的 $dfn$ 序。

后序遍历的最后一个就是整棵树的根结点,在中序遍历里根结点左端的点在结点的左子树,根结点右端的点在结点右子树。

通过中序遍历和后序遍历推出前序遍历,就是用分治的思想,拆分区间。

表达式树

用树型结构表达一个算式。一般而言,表达式树的中序遍历就是我们常见的形式。


分为有向图无向图。结点和边可能带权。

有两个集合 $V,E$ 表示顶点和边,边连接结点。

每个节点有一个参数表示进入的边数和出去的边数,称为度数

重边:几条性质相同的边(连接结点一致,方向一致)。

自环:一条连接了两个相同结点的边。

简单图:无重边,无自环的图。

完全图:指任意两个结点都存在边的图,有 $\frac{n(n-1)}{2}$ 条边。(这里指无向图)


图的存储

一般有 $3$ 种方式:邻接矩阵,邻接表,链式前向星。

邻接矩阵空间复杂度 $\mathcal O(n^2)$ ,一般用于稠密图。

邻接表空间复杂度 $\mathcal O(m)$ 需要动态申请,一般用 std::vector 实现。

链式前向星用类似于链表的结构组成,和邻接表类似,不过不需要动态申请内存。


图论算法

单源最短路径算法:$\text{Dijkstra,SPFA}$ ,时间复杂度分别为 $\mathcal O(n\log n),\mathcal O(kn)$ 。

多源最短路径算法:$\text{Floyd,Johnson}$ ,时间复杂度分别为 $\mathcal O(n^3),\mathcal O(nm\log m)$

最小生成树:$\text{Prim,Kruskal}$ ,时间复杂度 $\mathcal O(n^2),\mathcal O(m\log m)$ 。

欧拉回路:一笔画问题,只能最多 $2$ 个奇数度的结点。


数论

进制

$k$ 进制转 $10$ 进制:

$(\overline{a_1a_2\dots a_m})_k=a_m\times k^0+a_{m-1}\times k^1+a_{m-2}\times k^2+\dots a_{1}\times k^{m-1}$

$10$ 进制转 $k $ 进制:

将这个数除以 $k$ 直到比 $k$ 小,把每一次得到的余数从小位到大位组合,就是 $k$ 进制下的答案。这个方法被称为短除法

这里仅仅讨论非负整数