初赛整理
初赛整理
1 IT 发展历史
- 1946年 第一台计算器埃尼阿克。
- 计算机应用:计算,数据储存处理,通信,辅助工作。
- 第一个程序员:Ada,有为此命名的程序语言。
- 计算机:图灵奖,数学:菲尔兹奖,物化生经济文学和平:诺贝尔奖。
- IEEE:电气与电子工程师协会。
- ACM:美国计算机学会。
- CCF:不多介绍,懂得都懂。
注:
- 图灵奖由 ACM 建立
- 获得图灵奖的华人教授只有一人:姚期智。
- 图灵是英国人。
2 计算机组成
冯诺依曼结构,输入设备,输出设备,运算器,控制器,储存器。
2.1 CPU
字长:32位,64位,指每次指令可以处理多少位的数据。
主频:2.4GHz,处理速度。
内存:8GB,“临时存储”,RAM 储存信息关机会消失。
位 bit:一个 01,字节 Byte:8个01。
空间转换:过水已隐藏。记住 \(2^{10}=1024\)。
硬件:摩尔定律:每过 18 个月,同样面积,储存空间和运行速度翻一番。
通常说的 32 位,64 位指 bit。
2.2 软件系统
操作系统:Windows,DOS,UNIX,LInux,MacOS,Android,IOS,鸿蒙。
应用软件:浏览器,办公软件,游戏。
程序:机器语言(CPU看得懂),汇编语言,高级语言。
2.3 编码:
文字,图片,声音都可以变成 01 串。
文字可以为 ASCII 编码,GBK 编码,utf-8 编码(3个字节)
图片:黑白(01,一个像素点由 1 个 bit 组成)、24 位彩色 (RGB,一个像素点由 24 位 bit 组成)。
图片:jpg,gif,png,tiff,jpeg。
文档:txt,docx,pdf。
声音:mp3
视频:avi,rm,mp4,mkv。
可执行文件:exe(Windows),无(Linux)。
2.4 NOI系列
NOI:1984,中国计算机协会(CCF)
NOIP:1995-2019
可以带:文具(不能带稿纸),衣服,水,证件。
2022年后只能用 c++。
2.5 程序设计
编译:代码-可执行文件(机器码)C/C++,Pascal。
解释:一行一行运行:Python,JavaScript,PHP,BASIC。(脚本)
时间复杂度:数据规模增长和运行时间增长的趋势。
编译器:将一种(高级)语言,翻译成另一种(低级)语言(通常是)。
自然语言:人话。中文,英文,法语,俄语。
3 基础算法
3.1 排序
计数排序:\(O(a+n)\) 不基于比较。
选择排序:\(O(n^2)\) ,不稳定。每次选择当前最值。
冒泡排序:\(O(n^2)\) 稳定。做 \(O(n)\) 次全序列比较获得最值。
插入排序:\(O(n^2)\) 稳定。重新构造序列往里插入。
归并排序:\(O(n\log n)\),稳定,需要额外空间。
快速排序:不稳定 \(O(n\log n)\),不稳定,最坏 \(O(n^2)\) ,不过在随机化下难以出现。
堆排序:不稳定 \(O(n\log n)\) 。
稳定:两个数据相同,排序后,其相对位置不变,不稳定就是相对位置改变。
3.2 贪心
用局部最优,从而引出全局最优,目光短浅,需要证明。
过水已隐藏。
4.3 二分
过水已隐藏。
4.4 递推递归分治
过水已隐藏。
4 数据结构
4.1 栈
过水已隐藏。
出栈计数用卡特兰数来计算。
4.2 队列
过水已隐藏。
4.3 树
过水已隐藏。
4.4 二叉树
设二叉树中叶子结点个数为 \(a\),有两个儿子的节点个数为 \(b\),那么有 \(a=b+1\)。
- 证明:
- 设 \(m\) 为二叉树边数,有一个儿子的节点个数为 \(c\),总结点个数为 \(b\),那么有:\(n=m+1=a+b+c\),而因为 \(m=c+2\times b\),所以有 \(a=b+1\)。
4.5 图
过水已隐藏。
5 数学问题
5.2 进制转换
对于正数来说,这个都很熟悉,注意不同进制下只是数的不同表示,但是数是一样的。
对于小数来说,其他进制转十进制仍然相同,十进制转其他进制时需要乘而不是短除,当然乘法只对小数位来说,对于正数部分处理方法仍然相同。
5.3 运算符
&& 的优先级比 || 要高。具体所有运算符的优先级在下面的图中。
5.4 原码反码补码
对于正数来说,原码等于反码等于补码,而对于负数来说,反码是原码除了符号为之外其余位取反得到,而补码等于反码加一。
举个例子,这里以八位二进制举例。
最高位是符号位,例如:\(\texttt{1=(00000001),-1=(10000001)}\),补码的存在,是为了方便我们的加法:\(\texttt{-1+1=(00000001)+(11111111)=(00000000)}\),这样,如果加上一个负数,我们就在原码上进行计算,就可以通过溢出来保证按位置加法的正确性。
5.5 复杂度分析
这里主要讲解主定理及其证明。
主定理内容如下:
-
证明:
-
首先我们关注到这个分治复杂度的式子,第一层只有一个,复杂度 \(f(n)\),而第二层一共有 \(a\) 个,数据规模都是 \(\frac{n}{b}\),也就是说复杂度应该是 \(a\times f(\frac{n}{b})\),这样到最后一层第 \(k\) 层,我们有 \(a^k\times f(\frac{n}{b^k})\)。
所以我们能够得到:\(T(n)=f(n)+a\times f(\frac nb)+...a^k\times f(\frac a{b^k})\)。
不难发现 \(k=\log _bn\)。
到这里我们设 \(f(n)=n^d\),对于一般的 \(f(n)\) 证明较为复杂,把证明放在引用中,
我们整理如下:
\[T(n)=n^d(1+\frac{a}{b^d}+\frac{a^2}{b^{2d}}+...) \]不难发现后面是等比数列,令 \(q=\frac{a}{b^d}\),那么有:\((1-q)T(n)=n^d(q^{k+1}-1)\)。
接下来我们分情况来讨论:
- 如果 \(q=1\),那么这个时候等比数列公式不再生效,这个时候 \(T(n)=O(n^d\log n)=O(f(n)\log n)\),对应于上面第二种情况,也就是 \(f(n)=n^d=n^{\log_ba}\)。
- 如果 \(q>1\),也就是 \(a>b^d,d<\log_ba,f(n)<n^{\log_ba}\),当 \(k\) 越来越大的时候,\(q^{k+1}\) 趋值于无穷大,所以差不多是 \(T(n)=q^kn^d=\frac{a^k}{b^{kd}}\),因为 \(k=\log _bn\),所以我们有 \(T(n)=a^{k}=a^{\log_bn}=n^{\log _ba}\),最后一步用到了对数的性质:设 \(b^\alpha=n,b^\beta=a\),那么有:\(b^{\alpha\beta}=n^{\beta}=a^{\alpha}\),由此可以得到:\(a^\alpha=a^{\log_bn}=n^\beta=n^{\log_ba}\)。
- 如果 \(q<1\),也就是 \(f(n)>n^{^{\log_na}}\),那么当 \(k\) 越来越大的时候,\(q^{k+1}\) 趋值于无限小,所以我们有 \(f(n)=O(n^d)\)。
-
至此,主定理证明完毕。
6 真题选讲
6.1 2007年提高组
- 运算符优先级:
以及有 \(¬ ,∧,∨\) 分别是非交并。
-
NOIP 复赛推荐语言环境:g++,gcc,free pascal
-
关于 NP,NPC,和 P 问题的关系:
P 问题指的是在多项式时间内有解的问题,NP 问题指的是可以用多项式时间验证答案是否正确的问题,通常来说可能存在多项式算法但难以验证,NPC 问题是指有若干个 NP 问题可以规约到一个 NPC 问题,也就是说,NPC 问题不会比这些 NP 问题简单,如果这个 NPC 问题能够在多项式时间内解决,那么这些 NP 问题同样也可以在多项式时间内解决。
也就是说,2007 年那个题,NP 问题包含 P 问题,NPC 问题目前没有找到多项式时间的算法。
NPH 问题为有多个 NP 问题可以规约到它,但它可以不是一个 NP 问题。
-
约瑟夫问题递归式:
\[J(1)=1\\ J(2n)=2J(n)-1\\ J(2n+1)=2J(n)+1 \]结论:答案就是 \(n\) 的二进制向左循环一位。
-
注意传参时只会复制,所以一切操作不会影响到主函数内的变量。
-
一定要注意是 C 语言还是 C++ 语言。
-
第 \(28\) 题题解:
(连续邮资问题)某国发行了n 种不同面值的邮票,并规定每封信最多允许贴m 张邮票,在这些约束下,为了能贴出{1,2,3,…,maxvalue}连续整数集合的所有邮资,并使maxvalue 的值最大,应该如何设计各邮票的面值?例如,当n=5、m=4 时,面值设计为{1,3,11,15,32},可使maxvalue 达到最大值70(或者说,用这些面值的1 至4 张邮票可以表示不超过70 的所有邮资,但无法表示邮资71。而用其他面值的1 至4 张邮票如果可以表示不超过k 的所有邮资,必有k≤70)。
下面是用递归回溯求解连续邮资问题的程序。数组x[1:n]表示n 种不同的邮票面值,并约定各元素按下标是严格递增的。数组bestx [1:n]存放使maxvalue 达到最大值的邮票面值(最优解),数组y[maxl]用于记录当前已选定的邮票面值x[1:i]能贴出的各种邮资所需的最少邮票张数。请将程序补充完整。
我们考虑这个递归过程,注意到 \(i\) 为目前填的这一位,而 \(r\) 是目前的 \(\texttt{maxvalue}\)。
首先第 \(6\) 个位置一定是往下递归,故填的是 \(\texttt{backtrace(i+1,r)}\)。第 \(5\) 个空是我们的枚举下界,由题目可以知道需要保证 \(x\) 严格递增,所以枚举下界一定是 \(\texttt{x[i-1]+1}\)。
当前说了 \(r\) 是目前的 \(\texttt{maxvalue}\),但其实严格来说,由于 \(\texttt{y[r]=maxinf}\) ,所以 \(r\) 应该是 \(\texttt{maxvalue-1}\) ,所以 \(4\) 应该是 \(\texttt{r-1}\)。当我们加入完之后,最开始的我们需要更新 \(y\) 数组,由于 \(i\) 已经加一,所以当前的我们需要更新 \(\texttt{x[i-1]}\) 的贡献,那么这个贡献我们是需要从原先的最值那里加上若干张 \(\texttt{x[i-1]}\) 得到,而原先的最值就是 \(\texttt{x[i-2]}\)。同时由于我们使用的张数不应该大于等于 \(m\),否则没有往里面加 \(\texttt{x[i-1]}\) 的余地,所以我们的最大面值应该是 \(\texttt{x[i-2]*(m-1)}\)。这就是第 \(1\) 个空的答案。同样,\(2\) 和 \(3\) 应该是相同的,且容易知道 \(k\) 枚举的是我们填了多少张 \(\texttt{x[i-1]}\),所以我们应该填 \(\texttt{x[i-1]*k}\)。
6.2 2020年提高组
-
第 \(18\) 题题解:
-
这个题目的难点在于其比较长,难以把握这个代码的意思,其实这个代码的作用是一个双向搜索,表示把 \([0,m]\) 和 \([m,len]\) 这两端区间内的字符向左循环一维或向右循环一维,看是否相等。这里的双向搜索使用两个队列分别扩展来实现的。
选项其实自己模拟一下就可以得出,在复杂度分析那里我不知道为什么分析出一个 \(n^4\) 的复杂度来,反正肯定不是 \(n!\),双向一定带平方。
-
第 \(20\) 题题解:
-
这个题一定要注意死扣这个题给定的定义是什么。如果死扣题目提示的话即使不是很懂这个题目在干什么也可以做对。
-
第 \(15\) 题题解:
-
1948 年,香农将热力学中的熵引入信息通信领域,标志着信息论研究的开端。
6.3 洛谷SCP初赛
- 源代码,预处理,编译,优化,链接,可执行文件。是这样一个过程。所以连接器的功能就是把源代码转换成可执行程序。注意编译的时候不会编译头文件。
- 斐波那契堆优化 dijkastra 的复杂度是 \(O(m+n\log n)\)。原因是每一条边只会走一次,去最小值时堆内共有 \(n\) 个数,故一次操作是 \(n\log n\)。
- 选择排序无论什么情况复杂度都是 \(n^2\),而冒泡排序,插入排序不是这样。
6.4 J 的初赛
题目也太无聊了,竟然还有用溢出来排除选项的。就一个点,牵扯到 ccf 的一些规则:
- C.CSP-JS第二轮实行网上注册、报名,未通过网上报名的认证者可向所在省份特派员申请获得第二轮参加认证的资格。
- 这句话是错的,未通过网上报名的认证者没有参加 CSP-JS 第二轮的机会。
6.5 2019提高组
分数 69.5,不是很满意,只是比分数线高 9.5 分。
原因:错了一些弱智题。
- 由数字1, 1, 2, 4, 8, 8所组成的不同的4位数的个数是()
这种题我们分类讨论,先考虑 \(1,2,3,8\) 的情况,是 \(4!\) 种,再考虑 \(1,1,8,8\) 的情况,是 \(6\) 种,然后考虑其余情况,其余情况是有两个相同,其余都是一个的情况,这种情况通过枚举一共有 \(6\) 种组合方式,而每种里面通过多重集的排列一共有 \(12\) 中排列方式,所以答案是 \(102\)。
- 一些数字可以颠倒过来看,例如0、1、8颠倒过来还是本身,6颠倒过来是 9,9颠倒过来看还是6,其他数字颠倒过来都不构成数字。类似的,一些多位数也可以颠倒过来看,比如106颠倒过来是901 。假设某个城市的车牌只有5位数字,每一位都可以取0到9。请问这个城市有多少个车牌倒过来恰好还是原来的车牌,并且车牌上的5位数能被3整除?
我们主要来考虑被三整除这个限制,不难发现,中间的这三个数要么是 \(0\),要么是 \(1\),要么是 \(8\)。这就表明,中间的数构成了 \(3\) 的剩余系,也就是说,无论其余 \(4\) 位选什么,我们可以通过选中间的数来使得整个数合法,所以总的方案数为 \(5\times 5=25\)。
- 第 \(16\) 题第 \(3\) 问
一定要手玩准确才可以,这个题不该错。
- 第 \(18\) 题
需要注意这个题的意思是给定两个字符串,求在 \(s\) 连续删除至多多少个字符后,\(t\) 仍然是 \(s\) 的子序列。
其实只要明白了这个题目的意思,整个题也就迎刃而解了。
- 程序输出时,suf数组满足:对任意0≤i<slen,suf[i] ≤suf[i+1]。( )
解析:对。从15至19行可以看出,sub数组的值是从尾部往前减小或不变,所以suf[i] ≤suf[i+1]。
- 当t是s的子序列时,输出一定不为0。( )
解析:错。有题目目的可知,当t==s时输出为0。
- 程序运行到第23行时,“j-i-1”一定不小于0( )
解析: 错。若第一循环时while不执行,则j-i-1为-1,如s=”bacb”,t=”ac”。
- 当t是s的子序列时,pre数组和suf数组满足:对任意0≤i<slen,pre[i]>suf[i+1]+1( )
解析:错。由含义可知若t是s子序列,t[0..pre[i]-1],t[sub[i+1]+1..lent-1]是s[0..i],s[i+1..lens-1]的子序列,不会重叠,即pre[i]-1< sub[i+1]+1,即pre[i] <= sub[i+1]+1。
- 若tlen=10,输出为0,则slen最小为( )。
A. 10 B. 12
C.0 D.1
解析:D。若t不是s子串(或t==s)输出都为0,但为保证程序执行,最少应输入一个字符。这是因为不能读入空串。
- 若tlen=10,输出为2,则slen最小为( )。
A.0 B.10
C.12 D.1
解析:C。输出为2说明slen最多连续删除2个后为10,所以最小为12。
- 完善程序第 \(2\) 题。
这个题非常好。首先我们注意到 \(b\) 的取值范围,我们令 \(f_i\) 为剩余石子数为 \(i\) 的时候是否必胜,我们考虑转移,转移就是枚举当前能选的所有决策 \(b\),令 \(f_i=mex\{ f_{i-b} \}\)。考虑到 \(b\) 的取值,我们设 \(trans\) 为当前能选择的决策,这里目前只考虑满足 \(a\) 这个条件即可。令 \(status\) 为 \(f_{i-65},...,f_{i-1}\) 的一个二进制压缩,然后我们考虑转移只需要考虑 \(trans\) 对应的 \(status\) 为是否为 \(0\),最后我们把当前状态放到 \(status\) 中即可。注意初始化,首先容易理解的是最低位为必败态,其余位为了不影响答案应该设置为 \(1\)。
6.6 2018年提高组
做了 \(81\) 分,但是无意义的失分仍然有十多分,这十分危险,这说明我仍然缺乏训练,或者态度不够端正 。
发现最近这几天的初赛题最后一个题都是属于那种不知道什么意思就不会做的类型,最后一个题首先是一个贪心,然后是一个 dp,其作用是把一些买的 \(b\) 的物品改成买 \(a\)。
这里有一个背包,\(f_{i,j}\) 表示考虑前 \(i\) 个物品,其中花在 \(a\) 上的钱有 \(j\) 这么多,其余钱买 \(b\) 的最小花费。这里用 \(01\) 背包优化掉了第一维。不难发现转移式是 \(f_{i,j}=\min(f_{i-1,j}+b_i,f_{i-1,j-a_i})\)。当然后面必须得保证 \(j\ge a_i\)。
更新答案比较显然,其实只要知道这个背包就可以做出这个题来了。
实际上这种题在做的时候应该首先关注到 \(f\) 状态的更新方式,虽然挖了一个空,但通过更新答案的方式不难发现 \(f\) 数组的意义是什么。
7 引用
-
[第 \(18\) 题题解](