10_Python算法+数据结构笔记-钢条切割:自底向上实现/重构解-最长公共子序列-欧几里得算法

b站视频:路飞IT学城
https://www.bilibili.com/video/BV1mp4y1D7UP


个人博客
https://blog.csdn.net/cPen_web

#91 钢条切割问题:自底向上实现

#注:动态规划的写法,不用递归,自底向上的写法,先算r1、再算r2、r3 ……

图示

from cal_time import cal_time

p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 21, 23, 24, 26, 27, 27, 28, 30, 33, 36, 39, 40]

@cal_time
def cut_rod_dp(p, n):
    r = [0]  # DP,需要把它存起来。长度是0时 值是0。相当于递归条件
    for i in range(1, n+1): # 循环 从1 到 n,循环n次。r1 时 i就表示1
    # 相当于 从小到大 求r1、r2、r3……
        # 按照递推式来写
        res = 0
        for j in range(1, i+1):     # j相当于 1<=i<=n ,j相当于表达式里的i
            # 注:左边不切割 右边切割
            res = max(res, p[j] + r[i - j])   # 原写法是递归,现在写法 r[i-j]就是递推式里的 r n-i
            # 因为比i小的r 都已经append到r里面了,可以直接得到r[i-j]
        # 这个for循环结束之后 ,res就是r[i]这个值,算出来 把它放到r里
        r.append(res)
    return r[n]             # 最后算完后,要求r[n]

#注:和递归调用不一样的是 ,r[i-j]存起来,可以直接找
print(cut_rod_dp(p, 15))
#结果为
# cut_rod_dp running time: 0.0009980201721191406 secs.
# 42
#注:动态规划写法 比递归调用写法 快得多
#注:时间复杂度 是 n**2 (关于n的循环有2层),而 递归调用时间复杂度是 2**n
###### 钢条切割问题 -- 动态规划解法
# 时间复杂度:O(n**2)

图示

#注:动态规划解法,每次都是直接去取这个值,而不是把它再算一遍,所以快
#注:现在只是解决最大卖多少钱。怎么样输出应该怎么切?

DP思想 精简代码

def cut_rod_dp(p, n):
    r = [0]
    for i in range(1, n+1):
        res = 0
        for j in range(1, i+1):
            res = max(res, p[j] + r[i - j])
        r.append(res)
    return r[n]

#92 钢条切割问题:重构解

###### 钢条切割问题 -- 重构解
# 如何修改动态规划算法,使其不仅输出最优解,还输出最优切割方案?
# 对每个子问题,保存切割一次时左边切下的长度

图示
图示

#注:r[i] 最多的钱数
#注:s[i] 存切割方案的值。长度是i的钢条,最优方案 对应的左边这段是多长 (即 切1刀,不切的部分的长度)
#注:比如 i=1,r[1]  最优解 最多的钱数是1,s[1] 1的最优方案时 左边这段长为1 (1 、0切法)(因为切的话 左边不能为0,所以不可能0 1切法)
#注:比如 i=4,给个r[4],怎么输出最优方案?首先4来了,知道左边这块是2 ,不切割,出去了,还剩2。剩2这个问题 转化成了长度是2 的问题了,再看2 这个位置。2这个位置 左边是2,还剩0 (即没有了),完事了
# p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 21, 23, 24, 26, 27, 27, 28, 30, 33, 36, 39, 40]
p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 24, 30]	#注:价格表

def cut_rod_extend(p, n):   # p是价格表,n是钢条长度
    r = [0]  # 最优 钱数
    s = [0]  # 最优方案 对应左边这段 长度
    for i in range(1, n+1): # 从底向上的算 r1、r2、……
        res_r = 0            # 价格的最大值
        res_s = 0            # 价格最大值对应方案的左边不切割的长度
        for j in range(1, i + 1):
            if p[j] + r[i - j] > res_r:
                res_r = p[j] + r[i - j] # 更新 价格的最大值
                res_s = j               # 同时更新 左边的长度
                # 这个方案对应的是 j 和 i-j,i是现在算的长度,j是遍历的过程。
                # 比如说求r5 ,i是5,j是个循环 1,2,3,4;把5切成1+4,2+3……
        #注:这个循环结束后 res_r是 最大的价格,res_s 是 对应的这个价格下的j (左边不切的部分)
        r.append(res_r)
        s.append(res_s)
    return r[n], s      # s 最优方案 对应的左边长度

r,s = cut_rod_extend(p, 10)
print(s)
#结果为
# [0, 1, 2, 3, 2, 2, 6, 1, 2, 3, 10]

#注:输出后 怎么往回找,告诉别人 切成几和几。怎么输出方案?

def cut_rod_solution(p, n):
    # 首先输出 函数结果,调用那个函数
    r, s = cut_rod_extend(p, n) # 最优值 和 s表 出来了
    #注:n 对应的 s这个表,就是它 第1列要输出的值
    ans = []    # 存最后要切成 几几几
    while n > 0:    # 因为 最后 n会变成0
        ans.append(s[n])    # 首先把s表对应的n输出出去
        n -= s[n]           # 比如刚开始n=9,3进去了,再看6,把6表里的s[6]放进去……等于0 时退出
    return ans             # 返回 切割方案

print(cut_rod_solution(p, 10))
#结果为 [10]       #注:不切割
print(cut_rod_solution(p, 9))
#结果为 [3, 6]     #注:切成3 和 6

p = [0, 1, 5, 8, 9, 10, 17, 17, 20, 21, 23, 24, 26, 27, 27, 28, 30, 33, 36, 39, 40]
r, s = cut_rod_extend(p, 20)
print(s)
#结果 [0, 1, 2, 3, 2, 2, 6, 1, 2, 3, 2, 2, 6, 1, 2, 3, 2, 2, 6, 1, 2]
print(cut_rod_solution(p, 20))
#结果 [2, 6, 6, 6]
#注:20,s[20]=2,s[18]=6,s[12]=6,s[6]=6,剩0 不切割,结束。输出方案 [2,6,6,6]
#注:钢条切割问题 这种 重构写 ,即输出最优方案。 通过s[i]记录不动的部分。往回追 列表的过程 (Chasing back),来输出这个方案
#注:大部分 动态规划的问题 都是 Chasing back 往回追的过程。通过 记录1个其他信息的表,通过表往回追 ,来记录这个方案
###### 动态规划问题关键特性
# 什么问题可以使用动态规划⽅法?
#   ·最优子结构 (#注:即 递推式)
#       ·原问题的最优解中涉及多少个子问题
#       ·在确定最优解使用哪些⼦问题时,需要考虑多少种选择
#   ·重叠子问题
#注:最优化问题:最大、最小,求最优值的时候 考虑用动态规划,和贪心算法一样。贪心算法 是 动态规划的一个特例,用贪心来做,用动态规划一定能做 ;反过来 不一定成立
#注:涉及 最优子结构、重复子问题:递归的去想,算rn,假设r1,r2……r n-1都算出来了,看能不能算rn,如果能,递推式就出来了。递归能解,动态规划 应该也能解,不会重复计算
#注:学会看公式,学会自己写公式

#93 最长公共子序列

###### 最长公共子序列
# 一个序列的子序列是在该序列中删去若干元素后得到的序列。
#   ·例:“ABCD”和“BDF”都是“ABCDEFG”的子序列
# 最长公共子序列(LCS)问题:给定两个序列X和Y,求X和Y长度最大的公共子序列。
#   ·例:X="ABBCBDE" Y="DBBCDB" LCS(X,Y)="BBCD"
# 应用场景:字符串相似度比对
#注:俗称的 模糊查询 模糊搜索  并不是完全匹配,但是大部分一样
#注:基因工程 (人体基因ATCG 4个字母的字符串)、
#注:序列:字符串、列表 都是序列
#注:子序列:一个序列的子序列是在该序列中删去若干元素后得到的序列 (相对顺序要一致,中间可以不连续)
#注:子串:子串要连续的
#注:怎么 用算法 解决? 首先 暴力去做,所有情况都选举起来
#   ·思考:暴力穷举法的时间复杂度是多少?     答:2**(m+n) 二的(m+n)次方
#   ·思考:最长公共子序列是否具有最优子结构性质?
#注:长度是n的 序列,它的子序列 有多少个? 答:2**n 个 (跟钢条切割一个意思,n个字母,每个位置 可以有 可以没有)
#注:空串、它本身 都是1个子序列。比如说 ABCD、EFG 最长公共子序列 是 空序列,长度是0
#注:空序列 是 任何序列的子序列,它本身 也是它的子序列
#注:能不能用动态规划来做?答:首先 它 是 最优化问题 (最长),思考它有没有最优 子结构性质(能不能找到1个递推式,求出来 LCS(X,Y) )

lcs
最优解的递推式
lcs

# 	·c[i,j]表示Xi和Yj的LCS⻓度
#注:比如说:ABCD 和 ABD ,LCS="ABD"。D = D, 那么 ABC 和 AB , LCS="AB"
#注:如果Xm、Yn相等(即 最后1个位置上的字符相等),LCS长度 是k;那么 去掉最后1个字母,LCS长度是 k-1
#注:如果Xm、Yn不相等(即 最后1个字母不相等),LCS长度 要么是Xm去掉1个字母c[i,j-1]对应长度,要么是Yn去掉1个字母c[i-1,j]对应长度,这2个长度取最大值
###### 最⻓公共子序列
# ·例如:要求a="ABCBDAB"与b="BDCABA"的LCS:
#   ·由于最后⼀位"B"≠"A":
#       ·因此LCS(a,b)应该来源于LCS(a[:-1],b)与LCS(a,b[:-1])中更大的那⼀个

lcs

#注:情况1:i=0或j=0表示空串
#注:情况2:Xi=Yj,斜上方的值 + 1
#注:情况3:Xi≠Yj。从左边或者上边 取最大值,而不是从斜边取值,只去1个,而不是把2个都去了
#注:一来是X0,Y0, 空串和空串是 0……
#注:A、B两值,还是0,因为它两不相等
#注:BDCA和A,1,因为A相等
#注:BDCAB和A,1, 因为最后一位不相等,BDCA和A是1。所以1
#注:这是有条件的递归式,它是最优子结构,它只依赖于它的子问题 (依赖于它前面的值,左边的值,和斜向的值)
#注:按照动态规划的写法去写。构造二维列表,然后把最后那个值拿出来 (即右下角的值)
#注:第1行 和 第1列 都变成0,然后1行1行 填数。不会出问题,因为填任何值时,左上方3个值都已经有数了

#94 最长公共子序列:实现

def lcs_length(x, y):   # x、y 字符串 或 列表
    m = len(x)          # 长度
    n = len(y)
    # 构造二维列表。(外围)m+1行 (里面)n+1列的二维列表,因为有0的存在
    c = [[0 for _ in range(n+1)] for _ in range(m+1)]    # 二维的列表生成式
    for i in range(1, m+1): # 1到m。不考虑0那个位置,默认是0
        for j in range(1, n+1):  # 1到n
            if x[i-1] == y[j-1]: # i j 位置上的字符匹配的时候,来自于左上方+1
            # 因为 x、y是字符串,下标从0开始
                c[i][j] = c[i-1][j-1] + 1
            else:   #  如果不等于,左边的值和上边的值取最大
                c[i][j] = max(c[i-1][j], c[i][j-1])
    return c[m][n]  # 循环完了后,返回最后那个数

print(lcs_length("ABCBDAB", "BDCABA"))
#结果为 4
#核心:动态规划问题 难点是 递归式
# for _ in c: # 这样可以逐行打印二维列表
#     print(_)
#注:最优值 长度出来了,怎么得出 这个序列是什么?
#注:所有斜着过来的位置,都代表着匹配,从左上方得到的值+1,代表匹配过来的,因为条件决定。
#注:要找的匹配的位置,匹配的位置对于的就是最长公共子序列的字母
#注:方法:回溯 trace back,从最后一个值出发,不光计算长度,还要记箭头的方向

回溯

#注:如图示
#注:最后1个值不一样,左边和右边都相等,定义为来自于上方,往上找
#注:A和A匹配,A出去
#注:不匹配,往上走
#注:B和B匹配,B出去
#注:不匹配,往左走
#注:匹配,C出去
#……
#注:到第1行或者第1列 (即为0时),就停止

#注:推的时候 从前往后;找这条路径时 从后往前。这条路径所有斜向位置的值,就是我们想要的
#注:求其他位置也一样
#记箭头,用3个数来记
def lcs(x, y):
    m = len(x)
    n = len(y)
    c = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
    # b跟c建立方法一样。b同样的位置,用来记箭头的
    b = [[0 for _ in range(n + 1)] for _ in range(m + 1)] # 1 左上方 2 上方 3 左方
    # 不光记录c的值,还要给b赋值
    for i in range(1, m+1):
        for j in range(1, n+1):
            if x[i-1] == y[j-1]:    # i j 位置上的字符匹配的时候,来自于左上方+1
                c[i][j] = c[i-1][j-1] + 1
                b[i][j] = 1         # 给b赋值,左上方来的
            elif c[i-1][j] >= c[i][j-1]: # 来自于上方
                c[i][j] = c[i-1][j]
                b[i][j] = 2         # 给b赋值,来自于上方
            else:                       # 来自于左方
                c[i][j] = c[i][j-1]
                b[i][j] = 3         # 给b赋值,来自于左方
    return c[m][n], b

c, b = lcs("ABCBDAB", "BDCABA")
for _ in b:
    print(_)
#结果     这个表的箭头的方向
# [0, 0, 0, 0, 0, 0, 0]
# [0, 3, 3, 3, 1, 3, 1]
# [0, 1, 3, 3, 3, 1, 3]
# [0, 2, 3, 1, 3, 3, 3]
# [0, 1, 3, 2, 3, 1, 3]
# [0, 2, 1, 3, 3, 2, 3]
# [0, 2, 2, 3, 1, 3, 1]
# [0, 1, 2, 3, 2, 1, 3]
#注:有了这个数组,只需要从后往前 找回去,找这个匹配的位置,把这个位置输出
#回溯的算法
def lcs_trackback(x, y):
    c,b = lcs(x, y)     # 调用刚才写的lcs
    i = len(x)          # 从最后一个位置开始走
    j = len(y)
    res = []            # 存最长子序列 字符
    while i > 0 and j > 0:   # i或j=0时 退出
        if b[i][j] == 1:    # 来自左上方 => 匹配
            res.append(x[i-1])  # 注意下标,因为x、y是字符串,下标从0开始
            i -= 1              # 输出完 往左上方走
            j -= 1
        elif b[i][j] == 2:  # 来自上方 => 不匹配
            i -= 1              # 不append,往上走
        else:               # ==3 ,来自左方 => 不匹配
            j -= 1              # 不append,往左走
    # 退出后,res是最长公共子序列,但是是倒着的
    return "".join(reversed(res))

print(lcs_trackback("ABCBDAB", "BDCABA"))
#结果 BCBA
#注:这个算法的问题:只找一个,如果有多个最长公共子序列,只输出一个
#注:回溯算法 和 动态规划 搭配着来。动态规划只负责求最优值,需要把动态规划的最优值记录 和 动态规划的过程记录(方向)。trackback按照方向 来往回 回溯

#注:钢条切割问题 最后输出切割方案,也是一个回溯,因为记录了中间过程,往回回溯

精简代码

def lcs_length(x, y):
    m = len(x)
    n = len(y)
    c = [[0 for _ in range(n+1)] for _ in range(m+1)]
    for i in range(1, m+1):
        for j in range(1, n+1):
            if x[i-1] == y[j-1]:    # i j 位置上的字符匹配的时候,来自于左上方+1
                c[i][j] = c[i-1][j-1] + 1
            else:
                c[i][j] = max(c[i-1][j], c[i][j-1])
    return c[m][n]

def lcs(x, y):
    m = len(x)
    n = len(y)
    c = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
    b = [[0 for _ in range(n + 1)] for _ in range(m + 1)] # 1 左上方 2 上方 3 左方
    for i in range(1, m+1):
        for j in range(1, n+1):
            if x[i-1] == y[j-1]:    # i j 位置上的字符匹配的时候,来自于左上方+1
                c[i][j] = c[i-1][j-1] + 1
                b[i][j] = 1
            elif c[i-1][j] > c[i][j-1]: # 来自于上方
                c[i][j] = c[i-1][j]
                b[i][j] = 2
            else:
                c[i][j] = c[i][j-1]
                b[i][j] = 3
    return c[m][n], b


def lcs_trackback(x, y):
    c, b = lcs(x, y)
    i = len(x)
    j = len(y)
    res = []
    while i > 0 and j > 0:
        if b[i][j] == 1:    # 来自左上方=>匹配
            res.append(x[i-1])
            i -= 1
            j -= 1
        elif b[i][j] == 2:  # 来自于上方=>不匹配
            i -= 1
        else: # ==3 来自于左方=>不匹配
            j -= 1
    return "".join(reversed(res))

print(lcs_trackback("ABCBDAB", "BDCABA"))

#95 欧几里得算法

###### 最大公约数
#   ·约数:如果整数a能被整数b整除,那么a叫做b的倍数,b叫做a的约数。
#   ·给定两个整数a,b,两个数的所有公共约数中的最⼤值即为最⼤公约数(Greatest Common Divisor, GCD)。
#   ·例:12与16的最⼤公约数是4
###### 如何计算两个数的最大公约数:
#   ·欧几里得:辗转相除法(欧几里得算法)
#   ·《九章算术》:更相减损术
### 欧几里得算法:gcd(a, b) = gcd(b, a mod b)
# ·例:gcd(60, 21) = gcd(21, 18) = gcd(18, 3) = gcd(3, 0) = 3     # 不停取余

图示

#注:核心 gcd(a, b) = gcd(b, a mod b)  递归的式子
def gcd(a,b):
    if b == 0:      # 终止条件 有个数变成0
        return a
    else:
        return gcd(b, a % b)

print(gcd(12,16))
#结果为 4
#注:递归的写法,递归的写法会慢吗?不一定,因为这是伪递归,伪递归的效率和循环是一样的,编译器 会进行优化
# 非递归的写法
def gcd2(a, b):
    while b > 0:    # 循环终止条件 b变成0
        r = a % b    # 先记录 a模b
        a = b
        b = r
    return a        # 如果b=0时

print(gcd(12,16))
#结果为 4
###### 应用:实现分数计算
#   ·利用欧几里得算法实现一个分数类,支持分数的四则运算。
#注:计算机不支持分数,我们来实现一个分数类
class Fraction:
    def __init__(self, a, b):   # a分子、b分母
        self.a = a
        self.b = b
        x = self.gcd(a,b)       # 最大公约数
        self.a /= x     # 约分,化成最简形式
        self.b /= x

    def gcd(self, a, b):
        while b > 0:
            r = a % b
            a = b
            b = r
        return a

    def zgs(self, a, b):      # 最小公倍数
        # 12 16 -> 4
        # 3*4*4=48  #注:拿a、b除以 最大公倍数,这3个值再相乘,就是最小公倍数
        x = gcd(a, b)
        return a * b /x

    def __add__(self, other):   # 加法 add方法,直接在外面用2个对象 做加
        # self是1个分数对象,other也是一个分数对象
        # 1/12 + 1/20
        a = self.a  #注:a/b + c/d
        b = self.b
        c = other.a
        d = other.b
        fenmu = self.zgs(b, d)  # b和d最小公倍数
        fenzi = a * fenmu / b + c * fenmu / d
        return Fraction(fenzi, fenmu)

    def __str__(self):  # 打印出分母的格式
        return "%d/%d" % (self.a, self.b)

f = Fraction(30,16)
print(f)
#结果为 15/8
a = Fraction(1,3)
b = Fraction(1,2)
print(a+b)
#结果为 5/6
#注:这是加法;减法类似;乘法  分子一乘、分母一乘 再约分(通过最大公约数约分)
# def __add__(self, other):   # 加
# def __sub__(self, other):   # 减
# def __mul__(self, other):   # 乘
# def __divmod__(self, other):# 除
#注:数学上 数论:专门研究整数,最大公约数这是最基本的,密码学 基于数论的理论

精简代码

class Fraction:
    def __init__(self, a, b):
        self.a = a
        self.b = b
        x = self.gcd(a,b)
        self.a /= x
        self.b /= x

    def gcd(self, a, b):
        while b > 0:
            r = a % b
            a = b
            b = r
        return a

    def zgs(self, a, b):
        # 12 16 -> 4
        # 3*4*4=48
        x = self.gcd(a, b)
        return a * b / x

    def __add__(self, other):
        a = self.a
        b = self.b
        c = other.a
        d = other.b
        fenmu = self.zgs(b, d)
        fenzi = a * fenmu / b + c * fenmu / d
        return Fraction(fenzi, fenmu)

    def __str__(self):
        return "%d/%d" % (self.a, self.b)

a = Fraction(1,3)
b = Fraction(1,2)
print(a+b)

#96 RSA算法介绍

# RSA加密算法简介 (密码学的范畴)
###### 密码与加密
# ·传统密码:加密算法是秘密的
# ·现代密码系统:加密算法是公开的,密钥是秘密的
#   ·对称加密
#   ·非对称加密
#注:我们俗称的密码,在密码学中称为 口令,比如说 password 登录的用户名和密码,是用来验证的
#注:密码主要 用在 2个方向上 加密和解密
#注:传统密码:加密算法是秘密的。比如 凯撒密码:每个字母往后移3位;(其实 密码就是一种映射)
#   ·不好的地方:算法被截获了,就不行了。通过计算机 或者 枚举
#注:现代密码系统:加密算法是公开的,密钥是秘密的。密钥?一般是2个数
#注:RSA加密算法 属于非对称加密。2个密钥,1个密钥加密,1个密钥解密。
#注:如果 加密 解密 用1个密钥,称为 对称加密
#注:如果 1个密钥用来加密 1个密钥用来解密,称为 非对称加密
###### RSA⾮对称加密系统:
# ·公钥:⽤来加密,是公开的
# ·私钥:⽤来解密,是私有的
#注:linux系统,密钥认证 RSA_pub……,不用密码登录。生成的是1对,pub放在服务器上 公钥
#注:HTTP --》 HTTPS ,S 也是RSA

rsa

#注:密码学中 M叫做 明文,没有加密的 ;Bob先加密(使用公钥),C是加密之后的文字 (密文),Alice 通过私钥(自己的密钥)解密,就能获取M
#注:非对称加密 好处:公钥随便公开,因为公钥只用来加密,公钥解不开,只有通过私钥才能解开。
#注:如果使用私钥加密,公钥也可以解开,保证传输的安全性

#97 RSA算法测试

###### RSA加密算法过程
# 1. 随机选取两个质数p和q
# 2. 计算n=pq
# 3. 选取⼀个与φ(n)互质的小奇数e,φ(n)=(p-1)(q-1)
# 4. 对模φ(n),计算e的乘法逆元d,即满足 (e*d) mod φ(n) = 1
# 5. 公钥(e, n)      私钥(d, n)

# 加密过程:c = (m^e) mod n
# 解密过程:m = (c^d) mod n
#注:命令行 演示
#注:质数:约束只有 1和它本身的数 是质数
#注:加密算法 128位、256位、512位,这个位主要指p和q大小,质数越大,这个算法越难破解
#注:φ欧拉函数
#注:互质:2个数  最大公约数是1
#注:数学上 求 乘法逆元的算法 ……数论。d是唯一的 本例d是2011
#注:知道p和q,算了n、e、d。 (e, n)组成 公钥,(d, n)组成 私钥

#注:原文 用m来代替,这里面的 m看成整数。传输过程中 ,传输的信息不是整数,怎么办?(字符串、json、对象……)无所谓,任何东西在计算机里,往线上传 都是 0 1流,这个流都可以表示成1个整数,解析的过程是唯一的,再变回来就可以了
#注:^ 在数学上表示 次方,Python里 ** 表示次方
# 加密过程:c = (m^e) mod n  #注:c是密文,加密之后的
# 解密过程:m = (c^d) mod n
#注:数学上可以证明:费马定理、数论知识、欧几里得算法、乘法逆元的算法……

#注:为什么RSA加密算法破解不了?根源在于,2个质数 算乘法很容易,但是1个大整数 拆成2个质数 很难,只能一个一个试。乘容易,大数的拆分很难
#注:知道n=pq公开的,知道e,想求d,需要知道φ,φ怎么知道?需要知道p、q,想知道p和q就必须把n拆开,拆不开。一旦能拆开 比如说给公钥n,你能把它拆成2个质数,这一对密钥你破解了,而不是这个算法你破解了,破解了之后 它还可以生成新的密钥
#注:如果这个整数越大,它需要的时间就越长,破解的就越难
#注:在RSA算法 没有破解之前,都可以认为这个算法是能够保密的

#注:在乘法逆元这一步 ,用到了欧几里得算法,用到了最大公约数,它用到的是 扩展欧几里得算法
p = 53
q = 59
n = p*q
n
3127
fai = (p-1)*(q-1)
fai
3016
e = 3
fai / 3
1005.3333333333334
d = 2011
(e*d)%fai
1
e
3
n
3127
d
2011
n
3127
m = 87
c=(m**e)%n		#注:加密
c
1833
(c**d)%n		#注:解密
87

#98 算法课程总结

#注;最开始 算法的一些概念:时间复杂度、递归、查找和排序
#注:接下来介绍一些数据结构:包括线性的结构(线性表:列表、链表,栈、队列:迷宫问题,深度优先 广度优先思想),树,二叉树、二叉搜索树、AVL树 这样的一些索引结构。哈希表,AVL树 扩展出来的B+树 和 哈希表 是数据库的2种常用索引,用它来加速搜索查找
#注:2种算法进阶内容:算法导论书里 属于 算法的高级分析与设计的一种思想。贪心算法 和 动态规划
#注:贪心算法:识别出这个问题是不是贪心就可以了
#注:动态规划:对于初学者  不是特别能懂的
#注:最后 补充的2个小算法 欧几里得算法 和 RSA加密算法,属于初论部分

#注:做概率 有概率算法。Python的库 概率怎么来的,随机数怎么来的  比如random int怎么出来的
#注:统计量的一些算法,算法的各种思想引出来的  矩阵相关的算法,数论其他的算法
#注:相关资料:算法导论
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mycpen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值