深入理解AES加密算法:原理与Python实现
目录
- 深入理解AES加密算法:原理与Python实现
- 1. AES算法简介
- 2. AES加密解密流程
- 3. Python实现AES加密解密
- 4. 结论
深入理解AES加密算法:原理与Python实现
AES (Advanced Encryption Standard) 是目前最广泛使用的对称加密算法之一。它具有高效、安全和灵活的特点,被广泛应用于数据加密、通信加密以及各种安全协议中。本文将详细介绍AES算法的加密和解密流程,并通过Python从头实现AES的加密与解密,而不依赖任何加密算法第三方库。
1. AES算法简介
AES是一种分组加密算法,其主要特点如下:
- 分组长度:AES处理固定长度的分组,通常为128位(16字节)。
- 密钥长度:AES支持128位、192位和256位三种密钥长度。
- 轮数:加密过程中的轮数取决于密钥长度,分别为10轮(128位密钥)、12轮(192位密钥)和14轮(256位密钥)。
2. AES加密解密流程
AES的加密过程可以分为以下几个主要步骤:
- 密钥扩展:将初始密钥扩展为多个子密钥。
- 初始轮:初始轮中只执行AddRoundKey操作,即将明文与扩展后的第一个子密钥进行异或运算。
- 主要轮:根据密钥长度执行10、12或14轮迭代。每轮包括四个步骤:
- 字节代换 (SubBytes):非线性替换操作,对数据的每个字节使用S盒进行替换。
- 行移位 (ShiftRows):行移位操作,对数据矩阵的行进行循环移位。
- 列混合 (MixColumns):线性变换操作,对数据矩阵的列进行混合运算。
- 轮密钥加 (AddRoundKey):将当前数据与当前轮的子密钥进行异或运算。
- 最终轮:最后一轮中只执行SubBytes、ShiftRows和AddRoundKey操作,省略MixColumns操作。
解密过程是加密过程的逆过程,主要步骤如下:
- 初始轮:执行AddRoundKey操作。
- 主要轮:逆向执行AddRoundKey、逆MixColumns、逆ShiftRows、逆SubBytes操作。
- 最终轮:执行逆ShiftRows、逆SubBytes和AddRoundKey操作。
3. Python实现AES加密解密
以下是Python代码的完整实现:
# S盒 (SubBytes 使用)
S_BOX = [[0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76],[0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0],[0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15],[0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75],[0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84],[0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf],[0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8],[0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2],[0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73],[0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb],[0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79],[0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08],[0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a],[0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e],[0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf],[0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]
]# 逆S盒 (InvSubBytes 使用)
INV_S_BOX = [[0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb],[0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb],[0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e],[0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25],[0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92],[0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84],[0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06],[0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b],[0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73],[0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e],[0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b],[0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4],[0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f],[0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef],[0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61],[0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]
]# 密钥扩展需要的Rcon常量
RCON = [[0x01, 0x00, 0x00, 0x00],[0x02, 0x00, 0x00, 0x00],[0x04, 0x00, 0x00, 0x00],[0x08, 0x00, 0x00, 0x00],[0x10, 0x00, 0x00, 0x00],[0x20, 0x00, 0x00, 0x00],[0x40, 0x00, 0x00, 0x00],[0x80, 0x00, 0x00, 0x00],[0x1b, 0x00, 0x00, 0x00],[0x36, 0x00, 0x00, 0x00],
]# 字节代换
def sub_bytes(state):for i in range(4):for j in range(4):state[i][j] = S_BOX[state[i][j] >> 4][state[i][j] & 0x0f]# 逆字节代换
def inv_sub_bytes(state):for i in range(4):for j in range(4):state[i][j] = INV_S_BOX[state[i][j] >> 4][state[i][j] & 0x0f]# 行移位
def shift_rows(state):state[1][0], state[1][1], state[1][2], state[1][3] = state[1][1], state[1][2], state[1][3], state[1][0]state[2][0], state[2][1], state[2][2], state[2][3] = state[2][2], state[2][3], state[2][0], state[2][1]state[3][0], state[3][1], state[3][2], state[3][3] = state[3][3], state[3][0], state[3][1], state[3][2]# 逆行移位
def inv_shift_rows(state):state[1][0], state[1][1], state[1][2], state[1][3] = state[1][3], state[1][0], state[1][1], state[1][2]state[2][0], state[2][1], state[2][2], state[2][3] = state[2][2], state[2][3], state[2][0], state[2][1]state[3][0], state[3][1], state[3][2], state[3][3] = state[3][1], state[3][2], state[3][3], state[3][0]# 列混合
def mix_columns(state):for i in range(4):t = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i]u = state[0][i]state[0][i] ^= t ^ xtime(state[0][i] ^ state[1][i])state[1][i] ^= t ^ xtime(state[1][i] ^ state[2][i])state[2][i] ^= t ^ xtime(state[2][i] ^ state[3][i])state[3][i] ^= t ^ xtime(state[3][i] ^ u)# 逆列混合
def inv_mix_columns(state):for i in range(4):u = xtime(xtime(state[0][i] ^ state[2][i]))v = xtime(xtime(state[1][i] ^ state[3][i]))state[0][i] ^= ustate[1][i] ^= vstate[2][i] ^= ustate[3][i] ^= vmix_columns(state)# 辅助函数xtime,用于Galois域GF(2^8)的乘法
def xtime(a):return ((a << 1) ^ 0x1b) & 0xff if a & 0x80 else a << 1# 轮密钥加
def add_round_key(state, key_schedule, round_idx):for i in range(4):for j in range(4):state[i][j] ^= key_schedule[round_idx * 4 + j][i]# 密钥扩展
def key_expansion(key):key_symbols = [ord(symbol) for symbol in key]if len(key_symbols) < 4 * 4:for i in range(len(key_symbols), 4 * 4):key_symbols.append(0x01)key_schedule = []for r in range(4):key_schedule.append(key_symbols[r*4:(r+1)*4])for col in range(4, 4 * (10 + 1)):if col % 4 == 0:tmp = [key_schedule[col-1][1], key_schedule[col-1][2],key_schedule[col-1][3], key_schedule[col-1][0]]tmp = [S_BOX[b >> 4][b & 0x0f] for b in tmp]tmp[0] ^= RCON[col//4-1][0]else:tmp = key_schedule[col-1]key_schedule.append([key_schedule[col-4][i] ^ tmp[i] for i in range(4)])return key_schedule# AES加密函数
def aes_encrypt(plaintext, key):state = [[0] * 4 for _ in range(4)]for i in range(4):for j in range(4):state[i][j] = plaintext[i + 4 * j]key_schedule = key_expansion(key)add_round_key(state, key_schedule, 0)for round_idx in range(1, 10):sub_bytes(state)shift_rows(state)mix_columns(state)add_round_key(state, key_schedule, round_idx)sub_bytes(state)shift_rows(state)add_round_key(state, key_schedule, 10)ciphertext = []for i in range(4):for j in range(4):ciphertext.append(state[i][j])return ciphertext# AES解密函数
def aes_decrypt(ciphertext, key):state = [[0] * 4 for _ in range(4)]for i in range(4):for j in range(4):state[i][j] = ciphertext[i + 4 * j]key_schedule = key_expansion(key)add_round_key(state, key_schedule, 10)for round_idx in range(9, 0, -1):inv_shift_rows(state)inv_sub_bytes(state)add_round_key(state, key_schedule, round_idx)inv_mix_columns(state)inv_shift_rows(state)inv_sub_bytes(state)add_round_key(state, key_schedule, 0)plaintext = []for i in range(4):for j in range(4):plaintext.append(state[i][j])return plaintext# 测试加密解密流程
key = "2b7e151628aed2a6abf7158809cf4f3c"
plaintext = [0x32, 0x43, 0xf6, 0xa8, 0x88, 0x5a, 0x30, 0x8d, 0x31, 0x31, 0x98, 0xa2, 0xe0, 0x37, 0x07, 0x34]ciphertext = aes_encrypt(plaintext, key)
decrypted = aes_decrypt(ciphertext, key)print("Ciphertext:", ciphertext)
print("Decrypted:", decrypted)
4. 结论
通过以上实现,我们可以看到AES算法的复杂性和严谨性。尽管上述实现是简化版本,但它展示了AES加密和解密的核心思想。在实际应用中,使用经过验证的加密库来确保安全性更为妥当。然而,从头实现AES算法有助于深入理解加密过程的每个步骤及其安全性机制。
本文不仅阐明了AES算法的加密解密流程,还通过Python代码展示了如何实现AES加密和解密的核心功能,帮助读者对AES有更全面和深入的认识。
相关文章:

深入理解AES加密算法:原理与Python实现
目录 深入理解AES加密算法:原理与Python实现1. AES算法简介2. AES加密解密流程3. Python实现AES加密解密4. 结论 深入理解AES加密算法:原理与Python实现 AES (Advanced Encryption Standard) 是目前最广泛使用的对称加密算法之一。它具有高效、安全和灵…...

Redis中List数据类型常用命令
目录 1. 基本操作 (1)在列表的头部插入一个元素 (2)在列表的尾部插入一个元素 (3)获取列表的长度 (4)获取列表中的元素 2. 读取和修改 (1)获取列表的范围&…...

借助Aapose.Cells 使用 C# 在 Excel 中读取、添加和编辑线程注释
Excel 中的线程注释是协作工作的重要功能。它允许多个用户在共享文档中添加、编辑和查看对话线程。在某些情况下,我们可能需要以编程方式管理这些线程注释。在这篇博文中,我们将学习如何使用 C# 在 Excel 中读取、添加和编辑线程注释。 Aspose.Cells 是…...

关于c++ grpc 和 c# grpc 通信的问题 以及 grpc 认证问题
一、c 和 c# 通信 c# 端服务器 如果域名 输入的是 https ,则 c 端需要匹配使用,也就是c 端需要进行安全认证。如果是http 则c 端不需要认证(基于c#的grpc 未 通信成功) 参考如下网址可以写一个简单的 .net grpc服务器 (…...

C++进阶(14)类型转换、IO流
文章目录 一、类型转换C语言隐式类型转换强制类型转换 C类型转换的情况类型转换的函数(4个) 二、IO流1、缓冲区2、提高输入输出效率3、文件操作文件权限写操作 --- ofstream文本方式写入二进制方式写入 读操作 --- ifstream文本方式读取二进制方式读取 其…...

配置oss cdn加速静态资源访问 阿里云
效果对比 配置cdn下载速度对比 步骤 1: 登录阿里云控制台控制台主页,找到并点击“对象存储 OSS” 创建存储空间(Bucket) 设置权限 步骤 2: 获取外网访问地址 步骤 3 在 CDN 中使用该地址 复制该外网访问地址 打开全站加速 DCDN/域名管理 添…...

实现 前端框架 SPA 路由功能:Hash 模式与 History 模式的手动实现
前言 在前端框架(如 Vue.js、React 等)中,路由管理通常会配置一个 router 对象来定义 URL 路径与组件的映射关系。 路径(path): 这是浏览器 URL 的一部分,比如 /home 或 /about。组件(compone…...

去中心化的新时代:Web3技术的全球影响
随着技术的不断演进,Web3正引领互联网的去中心化新时代。相较于传统的Web1和Web2,Web3通过去中心化、区块链和智能合约等技术,正在重塑网络的运作方式。这一变革不仅提升了网络的安全性和透明度,也对全球经济、社会和文化产生了深…...

初始redis:List
列表 List 相当于数组或者顺序表。 对于List来说,两侧都可以插入和删除,时间复杂度是O(1)。 有很多的操作,比如 llen 可以获取List的长度,lrem 可以删除元素 ,lrange可以去一个字符串 , lindex可以根据下标…...

Java | Leetcode Java题解之第355题设计推特
题目: 题解: class Twitter {private class Node {// 哈希表存储关注人的 IdSet<Integer> followee;// 用链表存储 tweetIdLinkedList<Integer> tweet;Node() {followee new HashSet<Integer>();tweet new LinkedList<Integer&g…...

MVC与三层架构分层
1. 应用分层 应用分层类似公司的组织架构。我们进行项目开发时,最开始功能简单,前后端放在一起开发,但随着项目功能的复杂,项目会被前端和后端不同的团队接手,甚至更细粒度的团队。甚至后端开发也会根据功能再进行细分…...

Go语言基础--switch
在Go语言中,switch语句是一种非常强大的控制流结构,它允许一个变量的值与多个case进行比较,并根据匹配的结果执行不同的代码块。与C、C或Java中的switch不同,Go语言的switch更灵活,支持没有显式条件的switch࿰…...

【数字ic自整资料】AXI握手协议及outstanding
参考资料: ic基础|时序篇:握手协议valid和ready的时序优化_valid和ready握手信号-CSDN博客 https://zhuanlan.zhihu.com/p/365573848 1、AXI握手协议 当我们遇到时序违例时,通常采用的方式为插入寄存器(打拍)或者是…...

C++ //练习 18.13 什么时候应该使用未命名的命名空间?
C Primer(第5版) 练习 18.13 练习 18.13 什么时候应该使用未命名的命名空间? 环境:Linux Ubuntu(云服务器) 工具:vim 解释 当需要将实体限定在特定文件中,并且不会作用于不同文件…...

yum小bug
这个错误是在克隆的机子上安装mysql时,查看有无mysql发现的 [rootwebserve-2 backup] # yum list installed | grep mysql Repository cr is listed more than once in the configuration Repository fasttrack is listed more than once in the configuration 这…...

GDB的基本使用
我有话说 因为时间和精力原因,本文写的虎头蛇尾了,除了启动调试与程序执行以外只有少量截图演示,只是简单的说明。如果有需要可以联系我,我有时间的话会把演示补上,谢谢理解。 启动调试与程序执行 启动调试并传递参数…...

如何利用AI创作高质量的文章
讯飞星火 利用AI创作高质量的文章需要遵循以下步骤: 确定主题和目标受众:在开始写作之前,明确文章的主题和目标受众。这将帮助你确定文章的风格、结构和内容。 收集资料和信息:在撰写文章之前,进行充分的研究&#x…...

开源的量化交易领域平台vn.py(VeighNa)
一:vn.py(VeighNa)下的工具以及社区版和Elite版的区别 vn.py是一款广泛应用于量化交易领域的开源软件,它主要有以下用途和功能: 1. 交易系统开发框架:vn.py提供了一个完整的交易系统开发框架,可…...

选择搜索引擎进行搜索
<!DOCTYPE html> <html> <head><meta charset"utf-8"><title>选择搜索引擎进行搜索</title><script>function searchSelectedEngine() {var keyword document.getElementById(keyword).value;var engine document.getEl…...

安卓framework修改density
安卓平台,不同屏幕分辨率需要修改density值,以适配UI显示,比如字体大小等. 命令行下进入安卓SDK源码的device/目录 再根据不同芯片厂进入不同目录, 比如展锐就是 cd device/sprd, 高通是device/qcom/搜索关键字"ro.sf.lcd_density", grep -nr “ro.sf.lcd_density”…...

我们如何将数据输入到神经网络中?
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 下面我拿识别美女的例子来给大家介绍如何将美女的图片数据输入到神经网络中。 此例中,待输入的数据是一张图像。为了存储图像…...

基于python模板的药品名称识别系统设计与实现
博主介绍: 大家好,本人精通Java、Python、C#、C、C编程语言,同时也熟练掌握微信小程序、Php和Android等技术,能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验,能够为学生提供各类…...

【第五节】Win32汇编程序设计
目录 一、汇编的第一个“helloworld” 二、汇编中的标号 三、的使用 四、数据定义 五、全局变量 六、局部变量 七、结构体 八、结构体的访问 九、获取变量地址 十、函数 十一、分支与循环 十二、内联汇编 十三、裸函数的使用 一、汇编的第一个“helloworld” .38…...

2.1算法的时间复杂度与空间复杂度
本篇博客介绍算法的时间复杂度与空间复杂度 一、算法效率 算法好坏从时间和空间两个维度衡量 二、时间复杂度 1.概念 时间复杂度是算法中基本操作的执行次数,定量描述了算法的运行时间 2.注意 (1)时间复杂度是偏…...

Linux VSFTP 部署与配置
一、VSFTP 简介与应用 VSFTP(Very Secure FTP Daemon)是一款功能强大、安全可靠的FTP服务器软件,广泛应用于Linux/Unix系统中。它提供了高效的文件传输服务,并具备诸多安全特性,如用户认证、权限控制、SSL/TLS加密等。…...

【Docker】Docker Consul
docker consul Docker Consul 是一个用于服务发现和配置的开源工具,它是 HashiCorp 公司推出的一个项目。Consul 提供了一个中心化的服务注册和发现系统,可以帮助开发人员轻松地在 Docker 容器和集群之间进行服务发现和配置管理。 Consul 使用基于 HTT…...

diamond安装与使用
1.前言 diamond是一款用于蛋白质和翻译后DNA搜索的序列比对工具,专为大规模序列数据的高性能分析设计。其主要特点包括: - 与BLAST相比,蛋白质和翻译后DNA的成对比对速度快100倍至10000倍。 2. 参考 https://github.com/bbuchfink/diamond …...

flume--数据从kafka到hdfs发生错误
解决: #1.将flume自带的依赖删除 mv /opt/installs/flume1.9/lib/guava-11.0.2.jar /opt/installs/flume1.9/lib/guava-11.0.2.jar.bak #2.将hadoop的依赖发送到flume下 cp /opt/installs/hadoop3.1.4/share/hadoop/common/lib/guava-27.0-jre.jar /opt/installs/f…...

Android笔试面试题AI答之Kotlin(14)
文章目录 64. Kotlin中定义函数还是属性场景?使用属性的场景使用函数的场景示例 65. 阐述Kotlin中变量初始化有几种?其中lateinit、by lazy、delegates.notNull有什么区别 ?Kotlin中变量初始化的几种方式lateinit、by lazy、Delegates.notNull的区别 66. Kotlin中…...

博弈论,CF 1600E - Array Game
目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 1600E - Array Game 二、解题报告 1、思路分析 记最长递增前缀长度为L&a…...