读书笔记(python)–数据结构与算法
第七章 图及其算法
第八章 附加内容(本文)
前言
持续更新中,笔者学艺不精,可能存在错漏,请各位不吝赐教,笔者会尽快改正。
本章节为《Python数据结构与算法分析(第2版)》第八章“附加内容”的读书笔记,和原文的出入较大,需要学习数据结构与算法的小伙伴可以先去阅读原文。
一、RSA
https与http的不同,主要在于https多了一个SSL证书,这个SSL,对称加密算法、非对称加密算法、消息摘要(散列)算法都有使用,其中的非对称加密算法,目前使用较多的是RSA,这种加密方法兼容性较好。
虽然现在ECC算法表现优于RSA,但作为经典的非对称加密算法,RSA仍有研究与学习的价值。
1.同余定理
如果两个数 a 和 b 除以 n 所得的余数相等,我们就说 a 和 b“对模 n 同余”,记为 a ≡ b (mod n) 。
本节中的算法将利用 3 条重要的同余定理。
(1) 若a≡b (mod n),c≡d (mod n),则a±c≡b±d (mod n) 。
(2) 若a≡b (mod n),c≡d (mod n),则ac≡bd (mod n) 。
(3) 若a≡b (mod n),则ac≡bc (mod n) 。
2.幂剩余
如何计算 365535 的最后一位数(十进制下)?
扩展:如何能在不必算出 365535 的情况下,算出它对 n 的余数(十进制求最后一位,相当于n为10)。
利用同余定理(2):
设 x = 3a, y = 3b, a+b = 65535
则 x * y (mod n)= (x(mod n) * y) (mod n) = (x(mod n) * y(mod n))(mod n)
这样,就产生了一个递归的链条,可以先对x求余,再对y求余,最后两个余数相乘,再求余,最简单的思路为:
n = 10 # 对10求余
x = 1 # 初始化x
d = 3 # 幂运算的底数为3
z = 65535 # 幂运算的指数为65535
for _ in range(z):
x = x * d % n
print(x)
这样做,固然是没错的,但是,它很慢,需要循环65535次,这个循环里,x承担了所有,y相当于1,如果希望它能快点儿,那么,可以让x和y平均一些,比如尽量让两者相等。
def modexp(d, z, n):
if z == 0:
return 1
t = d * d % n
tmp = modexp(t, z // 2, n)
if z % 2:
tmp = tmp * d % n
return tmp
这里把目标分成了2份,如果分成3份或者更多,或许效率还有提升,但同为Olog(n)级别的算法,2份就已经足够了。
3.最大公因数与逆元
两年前面试的时候,还会有人问我类似如何“求最大公因数”或者“使用加减乘除和循环,求n的开方”等问题,近期的面试,则没人再问这些问题,或许是笔者的工作年限提高了,让面试官觉得这些问题太简单。不过,笔者自己的感觉是,程序员这两年的生存环境更恶劣了。
求n的开方,最经典的算法是牛顿迭代法,它是麦克劳林公式,或者说泰勒展开式的一阶应用,而求最大公因数,最经典的当属欧几里得算法:
给定两个数 a 和 b,要找到它们的最大公因数,可以反复计算 a - b,直到 a < b。当 a < b时,交换 a 和 b。当 a - b = 0 时,再次交换。此时,a就是最大公因数。这就是欧几里得算法:
def gcd(a, b):
if b == 0:
return a
elif a < b:
return gcd(b, a)
else:
return gcd(a - b, b)
利用python的特性,改良欧几里得算法:
def gcd(a, b):
return a if b == 0 else gcd(b, a % b)
对于 d = gcd(x, y),总能找到a、b使得 ax + by = d。
若 gcd(x, y) = 1,则有ax + by = 1,即 ax = 1 - by,即 ax ≡ 1 (mod y) 反过来说 by ≡ 1 (mod x),即a和x是关于模y的逆元,b和y是关于模x的逆元。
取两个数 x >= y ,返回元组(d, a, b),满足 d = gcd(x, y) 且 d = ax + by
def ext_gcd(x, y):
if y == 0:
return x, 1, 0
else:
d, a, b = ext_gcd(y, x % y)
return d, b, a - (x // y) * b
逆元这个操作,包括扩展gcd,在这个阶段尚看不出作用,它将在后面的RSA加密中,发挥自身的作用。
4.RSA 算法
在开始 RSA 算法之前,需要先提及一个定理,费马-欧拉定理:
若a、m为正整数,且gcd(a, m) = 1,则aφ(m) ≡1 (mod m)。
其中φ(m)是对模缩系的元素个数,就是比m小,且与m互素的正整数个数。
二、跳表
1.暂无
总结
持续更新中,尚未更新完成。