2023科协第二次MINI内训
写在前面
2023年3月26日,软件学院科协赛事部在EL大赛策划会议后举行了第二次内训。本次内训如愿线下举行,内容轻松愉快,讲述了如何将二进制运用到程序设计之中。算是一次成功的MINI内训。
回顾位运算
符号 | 描述 | 运算规则 |
---|---|---|
& |
与 | 两个位都为1时,结果才为1 |
或 | 两个位都为0时,结果才为0 | |
^ |
异或 | 两个位相同为0,相异为1 |
~ |
取反 | 0变1,1变0 |
<< |
左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
>> |
右移 | 各二进位全部右移若干位 |
一些简单的例子
用位运算判断一个数是否是奇数
1
2
3if (x & 1) {
printf("x is odd.");
}取出二进制数的倒数第$k$位
1
(x >> (k - 1)) & 1
将一个整数乘以$2^k$
1
x <<= k;
这仍然是一个easy的问题
二进制以字符串的形式描述
(1)将一个二进制数转化为十进制数
1 | int num = 0; |
(2)将一个十进制数转化为二进制数
重要思想: 其实数在计算机内本来就是二进制的,所以十进制数转化为二进制数就是依次取出二进制数的倒数第$k$位
快速幂算法
问题:如何快速求解$x^p$ 或$x^p$ mod r的值
在$O(n)$的时间内求解这个问题应该不是什么难事
能否在$O(log n)$的时间内求解这个问题
分治思想
当p 为偶数时, $n^p = (n^{p/2})^2$
当p 为奇数时呢? $p -1$ 是偶数
我们可以写递归函数解决
二进制分解
能否不用递归?
以求$x^{21}$ 为例:$(21)_{10}=(10101)_2$
$x^{16}$ | $x^{8}$ | $x^{4}$ | $x^{2}$ | $x^{1}$ | |
---|---|---|---|---|---|
每一位 | 1 | 0 | 1 | 0 | 1 |
Python参考代码
1 | def fast_pow(x, p): |
状态压缩
P2040 打开所有的灯 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目描述
这个灯很奇怪,点一下就会将这个灯和其周围四盏灯的开关状态全部改变。现在你的任务就是就是求要打开全部这些灯最少需要点几下。
例如
1 | 0 1 1 |
点一下最中间的灯【2,2】就变成了
1 | 0 0 1 |
再点一下左上角的灯【1,1】就变成了
1 | 1 1 1 |
达成目标。最少需要2步。
分析
像极了洛克王国打幽系徽章玩的小游戏
- 一个灯点1次和点3的效果是一样的
- 那么我们是不是可以枚举每个灯的状态
- 每个灯就是一个0或者1
- 可以用9位的二进制数(0~511)描述所有操作组合
C语言参考代码
1 |
|
注:这段代码在3*3的棋盘外面加上了“一层壳”,有效避免了边界的特别处理
改进
使用了Web CodeServer现场演示,PPT和内容存在网页中,可以在教室电脑上直接运行,无需投影/配环境