深入浅出程序设计竞赛(基础篇)

一、语言入门

1. 简简单单写程序

2. 顺序结构程序设计

P5705 【深基2.例7】数字反转

scanf("%c%c%c.%c",&a,&b,&c,&d);

P1425 小鱼的游泳时间

把时间转换成距 \(00:00\) 经过了多少分钟

P5708 【深基2.习2】三角形面积

三角形三边长 \(a,b,c\),面积 \(\sqrt{p(p-a)(p-b)(p-c)}\),其中 \(p=\frac{a+b+c}{2}\)

3. 分支结构程序设计

例 3-2

运算符优先级:

4. 循环结构程序设计

5. 数组与数据批量存储

P2615 [NOIP2015 提高组] 神奇的幻方

6. 字符串与文件操作

例 6-3

strcpy(s,"hello")

例 6-4

fgets(s,sizeof(s),stdin);
sscanf(s,"%d",&a);
sprintf(s,"%d",a);

例 6-7

char ch[10];
string s;
strcpy(ch,s.c_str()); // strncpy(ch,s.c_str(),10);
s = ch

P1598 垂直柱状图

值得一写

7. 函数与结构体

P1304 哥德巴赫猜想

哥德巴赫猜想:任一大于 \(2\) 的偶数都可以写成两个素数之和

二、初涉算法

8. 模拟与高精度

P1249 最大乘积

高精度的部分不再赘述,只考虑怎么分解

DP

取对数把乘积变成加法就可以用低精度背包得到决策

贪心

首先有 \(n(n+1)>(n-1)(n+2)\),据此不断调整可以得到答案为 \(2,3,\cdots,x,x+2,x+3,\cdots y\)

一种构造方法是找到最大的 \(\sum_{i=2}^{m}i\le n\),然后从 \(m\) 开始逐个 \(+1\) 至和为 \(n\)

P1045 [NOIP2003 普及组] 麦森数

\(2^{p}\) 的个位一定 \(\ne0\),所以 \(-1\) 很好处理

解方程 \(2^{p}=10^{q}\) 可以得到位数为 \(\lfloor p\lg2\rfloor+1\)

\(500\) 位可以高精快速幂,也可以高精乘低精(不压位,每次乘 \(2^{27}\)

9. 排序

P1116 车厢重组

冒泡排序交换相邻项次数 \(=\) 逆序对数

P1012 [NOIP1998 提高组] 拼数

邻扰

10. 暴力枚举

P2241 统计方形(数据加强版)

矩形的数量为 \(\frac{n(n+1)m(m+1)}{4}\)
边长 \(i\) 的正方形的数量为 \((n-i+1)(m-i+1)\)
长方形数量为矩形数量减正方形数量

时间复杂度 \(O(n)\)

P1088 [NOIP2004 普及组] 火星人

next_permutation(begin(),end())

P1217 [USACO1.5] 回文质数 Prime Palindromes

回文数只有 \(O(\sqrt{b})\) 个,所以可以打表

\(11\) 外,偶数位回文数一定不是质数

11. 递推与递归

P1044 [NOIP2003 普及组] 栈

卡特兰数

P1028 [NOIP2001 普及组] 数的计算

递归的常数优于递推,因为不需要计算 \(\lfloor\frac{n}{2}\rfloor+1\cdots n-1\)

P1259 黑白棋子的移动

容易从 \(n\) 递归到 \(n-1\)

oo...oo**...**--
oo...o--*...**o*
oo...o***...--o*

\(n\ge4\) 可以猜出递归边界就是 \(n=4\),手玩出来

oooo****--
ooo--***o*
ooo*o**--*
o--*o**oo*
o*o*o*--o*
--o*o*o*o*

P1228 地毯填补问题

公主的存在使得基本图形是缺一个角的正方形

把大正方形均分成四个小正方形,递归填公主所在的小正方形,中间放一个地毯就使剩下三个小正方形也缺了一个角

12. 贪心

经典模型:

哈夫曼编码

P4447 [AHOI2018初中组] 分组

sol 1

二分答案

check 时从小到大尝试把连续 \(mid\) 个分到一组。分完后把剩下的数尝试接在已有组的后面,如果有数不能接在任意一组后面那么不可行

sol 2

从小到大考虑每个数,每组可以用 \((len,end)\) 表示(长度,最后一个数)

对于数 \(x\),把它接在 \(end=x-1\)\(len\) 最小的组中,不能接到任意一组后面那么新建组

sol 3

13. 二分查找与二分答案

P1163 银行贷款

题意

利率可能 \(>1\),二分需要注意上界

倍增代替二分答案:设置当前答案 \(x\) 和增量 \(k\)。如果 \(x+k\) 可行,那么令 \(x\leftarrow x+k, k\leftarrow 2k\),否则令 \(k\leftarrow\frac{k}{2}\)\(k<\epsilon\) 时结束

14.搜索

数独

P1162 填涂颜色

sol 1

从边界的 \(0\) 开始搜,未被搜到的 \(0\) 就是在圈中的

sol 2

先按行数从小到大,再按列数从小到大,找到的第一个 \(1\) 的右下角一定是圈中的 \(0\),从这个 \(0\) 开始搜即可

三、简单数据结构

15. 线性表

P1449 后缀表达式

后缀表达式/逆波兰式:运算符在参数之后,严格从左到右计算(没有括号,不考虑优先级)

16. 二叉树

P1827 [USACO3.4] 美国血统 American Heritage

  • 前序遍历:根左右
  • 中序遍历:左根右
  • 后序遍历:左右根

前序遍历的第一个位置是根,中序遍历中以根为分界分成左右子树

表达式树

叶子是参数,非叶子是运算符,自底向上用根的运算符合并子树的值就能得到表达式的值

若所有运算都是双目运算,则表达式树是二叉树。前/中/后序遍历是前/中/后缀表达式

P1229 遍历问题

前后序相同而中序不同只有一种情况:只有一个儿子的结点,该儿子位于左/右子树

问题转化为求只有一个儿子的结点数。易证 \(u\) 只有一个儿子的充要条件是前序存在 \(uv\) 且后序存在 \(vu\)

习题 16-3

P1185 绘制二叉树

\(i\) 层结点的满二叉树的根在 \(f[i]\) 列,叶子在 \(g[i]\) 行。观察可得 \(f[1]=1,f[2]=3,f[i]=2f[i-1],g[1]=1,g[i]=g[i-1]+f[i]-f[i-1]\)

容易得到需要的坐标/长度,模拟

17. 集合

18. 图的基本应用

P3916 图的遍历

建反图。从 \(n\)\(1\) 枚举,标记能到达的点。每个点第一次被标记时就是答案

P2661 [NOIP2015 提高组] 信息传递

每个点只有一条出边意味着每个连通块中有且仅有一个环

P1127 词链

P1330 封锁阳光大学

每条边必须且仅能选一个端点,所以任意一条链都是 选-不选-选-不选 交替,有奇环则无解

因此一个连通块的答案是二分图左右部中较小的点数

P1363 幻象迷宫

显然如果当前棋盘和相邻棋盘都能走到 \((i,j)\) 那么 yes
把坐标模 \(n,m\) 转化为只在一个棋盘上走

一开始的想法是从 s 能走到环就 yes。hack:相邻的四个棋盘形成一个环

5 5
#.#.#
..#..
#####
.S#..
#.#.#

正解是记录走到 \((i,j)\) 能否走到,如果两次走到 \((i,j)\) 且模之前的坐标不同那么 yes

四、基础数学与数论

19. 位运算与进制转换

负数的二进制

反码:把绝对值的二进制取反
补码:反码 \(+1\)。全 \(0\) 表示 \(0\),全 \(1\) 表示 \(-1\)

减法:

小数的二进制

逻辑命题

徳·摩根定律:\(\overline{A}+\overline{B}=\overline{AB},\overline{A}\cdot\overline{B}=\overline{A+B}\)

实现了一定条件下与和或的转化

P1017 [NOIP2000 提高组] 进制转换

\(n=a(-R)+b\) 的思路不变

被除数 \(=\)\(\times\) 除数 \(+\) 余数,把商 \(+1\) 就能把余数调成正数

20. 计数原理与排列组合

P1866 编号

限制关系是包含的,从强到弱考虑

P2789 直线交点数

\(f[i,j]\) 表示 \(i\) 条直线形成 \(j\) 个交点是否可行,转移枚举接下来 \(k\) 条直线平行(不与已有的直线平行),新增 \(ik\) 个交点

bitset 优化,时间复杂度 \(\displaystyle O(\frac{n^{4}}{\omega})\)

21. 整除理论

P1414 又是毕业季II

考虑每个值是多少个数的约数

P2651 添加括号III

\(a[1]\) 肯定是分子,\(a[2]\) 肯定是分母,构造 \(a[1]/(a[2]/a[3]/\cdots/a[n])\),仅有 \(a[2]\) 是分母。判断能否将 \(a[2]\) 约分为 \(1\) 即可

P2660 zzc 种田

设宽为 \(n\),长为 \(m\) 的答案为 \(4f(n,m)\)
结论:每次删边长为 \(n\) 的正方形最优,即 \(f(n,m)=f(n,m-n)+n\)
边界是 \(f(0,\gcd(n,m))=0\),所以 \(f(n,m)=n+m-\gcd(n,m)\)
反证:如果所有正方形边长都 \(<n\),那么两条长边由不同的正方形覆盖,代价至少是 \(2m\)

posted @ 2023-07-24 15:30  ft61  阅读(1205)  评论(0编辑  收藏  举报