LeetCode 3336 题解:子序列最大公约数相等的对计数(DP 三状态枚举 + 记忆化递归)
LeetCode 3336 题解子序列最大公约数相等的对计数DP 三状态枚举 记忆化递归【免费下载链接】leetcodeLeetCode Solutions: A Record of My Problem Solving Journey.( leetcode题解记录自己的leetcode解题之路。)项目地址: https://gitcode.com/gh_mirrors/le/leetcode本文以 LeetCode 3336「最大公约数相等的子序列数量」为核心讲解如何用动态规划统计两个互不相交、且元素 GCD 相等的子序列对的数量。文章继承了原题解的「逐个元素三选一」思路并结合仓库中的 动态规划专题、最大公约数专题 与同类题目源码如 416. 分割等和子集深入剖析状态定义、转移方程与复杂度边界。读完你不仅能 AC 本题还能掌握一类「把元素划分到若干集合」的计数 DP 通用套路。题目描述与输入约束给你一个整数数组nums请你统计所有满足以下条件的非空子序列对(seq1, seq2)的数量子序列seq1和seq2不相交即nums中不存在同时出现在两个序列中的下标seq1元素的GCD等于seq2元素的 GCD。由于答案可能非常大请返回其对10^9 7取余的结果。输入约束决定了算法量级必须控制在n * m^2级别1 nums.length 200 1 nums[i] 200三个示例用于验证对题意的理解nums [1,2,3,4]输出1010 个 GCD 均为 1 的子序列对nums [10,20,30]输出22 个 GCD 均为 10 的子序列对nums [1,1,1,1]输出50。注意题面中「元素 GCD 等于 1 的子序列对有」下列出的 10 项只是示意列举实际计数的是具体的下标划分方案而不是被打印成相同样式的字面量这也是示例 3 能产出 50 的原因——每种子序列划分按下标唯一计数。前置知识与仓库关联本题的前置知识标注为动态规划实际还隐式依赖**最大公约数GCD**的计算。仓库中恰好有两篇与本题直接相关的专题文章可作为扩展阅读最大公约数专题系统梳理了三种 GCD 求法——定义法O(min(a,b))、辗转相除法O(log(max(a,b)))、更相减损术并指出「辗转相除 更相减损」结合可获得更稳的性能。本题代码中的math.gcd底层正是辗转相除法。动态规划专题开篇即点明「动态规划和查表的递归记忆化递归有很多相似的地方」并强调「定义状态是动态规划的核心」「时间复杂度打底就是状态总数」这些观点正是理解本题dp(i, gcd1, gcd2)设计的关键。GCD 概念上子序列的 GCD 是其中所有元素的最大公约数gcd(a, b, c) gcd(gcd(a, b), c)因此可以随着逐个放入元素逐步累积计算这为下面的三选一 DP 提供了前提。核心思路把元素逐个放入两个集合一类计数题的通用框架像这种要求把元素划分为若干个集合本题是两个集合 可丢弃的计数题通常考虑枚举元素逐个放入集合对每个元素枚举它放入哪个集合根据题目也可以不放入任何集合。本题正是这种「逐个元素三选一」的模型。与之相对的「枚举集合再考虑放入哪些元素」的方式由于集合个数通常远小于元素个数一般没有优势不推荐。注意这里说的是集合元素之间的顺序无影响。如果题目要求的是有序排列顺序有影响这种逐个放入的方式就不可行了。本题中对每个nums[i]恰好有三种决策放入seq1放入seq2不放入任何序列。当数组全部处理完后若seq1与seq2的 GCD 相同则这组划分方案对答案贡献 1。为什么可以用 DP无后向性与重叠子问题这个「逐个元素三选一」的过程天然满足 DP 的两大条件无后向性当前元素放入哪个集合只会影响后续状态中的gcd1/gcd2取值不会回头改变前面已确定的划分因此可以从左到右递推重叠子问题不同路径会到达相同的(i, gcd1, gcd2)状态比如[2,3]与[3,2]不同的放入顺序可能产生相同的 GCD 组合若不做记忆化暴力枚举所有三选一分支的时间复杂度是指数级的。仓库 动态规划专题 对此有明确的印证「递归中如果存在重复计算重叠子问题那就是使用记忆化递归或动态规划解题的强有力信号之一」。状态定义与转移方程状态定义定义dp[i][gcd1][gcd2]从下标i开始即尚未决策的元素为nums[i:]当前seq1的最大公约数为gcd1、seq2的最大公约数为gcd2的前提下剩余元素划分完毕后、两序列 GCD 相等的方案总数。最终答案为dp(0, -1, -1)其中-1表示对应序列尚未放入任何元素空序列没有 GCD用哨兵值-1区分边界条件dp[n][x][x] 1其中x的范围是[1, m]m为值域本题m 200。含义是所有元素都已决策完毕i n若两个序列都非空且gcd1 gcd2则这一种完整划分方案计数为 1否则为 0。转移方程对当前元素nums[i]枚举三种决策dp(i, gcd1, gcd2) dp(i 1, gcd(gcd1, nums[i]), gcd2) // 放入 seq1 dp(i 1, gcd1, gcd(gcd2, nums[i])) // 放入 seq2 dp(i 1, gcd1, gcd2) // 不放入任何序列转移中的一个小技巧当序列为空gcd -1时放入第一个元素后 GCD 应直接等于该元素本身即gcd(-1 哨兵, x) x代码中用gcd1 if gcd1 ! -1 else nums[i]处理。这也说明状态中的-1只是一个特殊哨兵并不参与真正的 GCD 计算。复杂度分析令n为数组长度m为数组值域状态个数为n * m^2每个状态的转移是O(1)时间复杂度O(n * m^2)。代入本题约束n 200, m 200约8 * 10^6量级的状态可以接受空间复杂度O(n * m^2)若用记忆化递归实际空间还包含递归调用栈开销。参考代码Python3记忆化递归原题解使用 Python3 的cache记忆化装饰器实现自顶向下 DPclass Solution: def subsequencePairCount(self, nums: List[int]) - int: MOD 10 ** 9 7 cache def dp(i, gcd1, gcd2): if i len(nums): if gcd1 gcd2 and gcd1 ! -1: return 1 return 0 ans dp(i 1, math.gcd(gcd1 if gcd1 ! -1 else nums[i], nums[i]), gcd2) dp(i 1, gcd1, math.gcd(gcd2 if gcd2 ! -1 else nums[i], nums[i])) dp(i 1, gcd1, gcd2) return ans % MOD return dp(0, -1, -1)代码要点拆解cache等价于手动维护memo[(i, gcd1, gcd2)]哈希表key 为函数参数元组value 为返回值这正是仓库 动态规划专题 中「查表的递归记忆化递归」的标准形态三个dp(...)分支分别对应「放入 seq1」「放入 seq2」「都不放入」与思路部分的三种决策一一对应每个状态在返回前对MOD取余防止累加溢出边界判断gcd1 ! -1保证两序列均为非空题目要求非空子序列对。关于记忆化递归 vs 迭代 DP 的选择仓库 动态规划专题 给出的建议同样适用于本题「没空间优化需求直接就记忆化否则用迭代 dp」——本题状态维度较多三维滚动数组优化收益有限记忆化递归是更直观、不易出错的写法。与仓库同类题目的横向印证本题「逐个元素三选一 累计 GCD」的模型在仓库中能找到多个可对照学习的姊妹题416. 分割等和子集同样是「元素放入两组」的划分模型F[i, v]表示前i个数能否组成和为v的子序列本质是背包问题它与本题的差异在于 416 的两个集合必须恰好覆盖所有元素相当于没有「不放入」这个第三选项且目标约束是「和相等」而非「GCD 相等」。494. 目标和将数组分成组和-组两组也是划分计数 DP可对照理解「集合划分 方案计数」的套路。365. 水壶问题 与 914 等 GCD 应用展示了 GCD 在判定类问题中的应用z是否能被gcd(x, y)整除与本题「用 GCD 作为状态维度」形成互补视角。从源码结构可以推断本题的价值在于把「GCD」这一数学算子与「集合划分计数 DP」结合GCD 的幂等、可累积性质gcd(gcd(a,b), c) gcd(a,b,c)使得「放入序列后只更新该序列的 GCD 一个维度」成为可能这是状态能压缩为三维的关键。总结识别模型看到「划分成两个或多个不相交集合 满足某个相等条件 计数」时优先考虑「逐个元素枚举放入哪个集合」的 DP 框架状态设计dp(i, gcd1, gcd2)把「处理到哪」和「两个集合当前 GCD」全部纳入状态用-1哨兵表示空序列转移即三选一放入 seq1 / 放入 seq2 / 都不放三个分支各对应一个子问题边界收口全部元素处理完后仅当两个序列非空且 GCD 相等时计数 1复杂度可控O(n * m^2)的时间与空间在n, m 200的量级下完全可行。扩展阅读最大公约数专题三种 GCD 求法动态规划专题记忆化递归与状态定义416. 分割等和子集集合划分 DP / 背包模型494. 目标和正负两组划分计数365. 水壶问题GCD 判定应用【免费下载链接】leetcodeLeetCode Solutions: A Record of My Problem Solving Journey.( leetcode题解记录自己的leetcode解题之路。)项目地址: https://gitcode.com/gh_mirrors/le/leetcode创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Claude Pro vs Max:从额度机制到Claude Code实战的选型指南

Claude Pro vs Max:从额度机制到Claude Code实战的选型指南

1. 先搞清楚你每个月掏的钱到底买到了什么很多人第一次看到 Claude 的订阅页面时,脑子里只有一个模糊的印象:Pro 是 20 美元,Max 是 100 美元,Max 更贵所以更强。但"更强"具体强在哪里、多花的 80 美元到底换来了什么、…

2026/9/19 20:55:23 阅读更多 →
react-beautiful-dnd 常见配置问题排查指南:从 console 诊断到渲染修复

react-beautiful-dnd 常见配置问题排查指南:从 console 诊断到渲染修复

react-beautiful-dnd 常见配置问题排查指南:从 console 诊断到渲染修复 【免费下载链接】react-beautiful-dnd Beautiful and accessible drag and drop for lists with React 项目地址: https://gitcode.com/gh_mirrors/re/react-beautiful-dnd react-beaut…

2026/9/19 20:55:23 阅读更多 →
Excel文本日期转换全攻略:从DATEVALUE到Power Query

Excel文本日期转换全攻略:从DATEVALUE到Power Query

1. 文本转日期为什么总翻车:先搞懂Excel的底层逻辑1.1 一个让无数人抓狂的场景从ERP系统导出的销售明细、从网页复制粘贴的订单记录、从同事那里拿到的考勤表,打开一看,日期那一列全是左对齐的文本——“2024/3/15”“2024-03-15”“20240315…

2026/9/19 20:55:23 阅读更多 →

最新新闻

跨平台下载工具NDM安装配置全攻略:Windows与macOS多线程下载实战

跨平台下载工具NDM安装配置全攻略:Windows与macOS多线程下载实战

1. 为什么我最终把主力下载工具换成了NDM很多人第一次听到NDM(Neat Download Manager)这个名字,第一反应是"又一个下载器?IDM 不香吗?"。我一开始也是这个态度,直到有段时间需要频繁在 Windows 和…

2026/9/19 21:42:45 阅读更多 →
Hugo 中 resources.ExecuteAsTemplate:用 Go 模板动态生成资源的权威指南

Hugo 中 resources.ExecuteAsTemplate:用 Go 模板动态生成资源的权威指南

Hugo 中 resources.ExecuteAsTemplate:用 Go 模板动态生成资源的权威指南 【免费下载链接】hugo The world’s fastest framework for building websites. 项目地址: https://gitcode.com/gh_mirrors/hu/hugo resources.ExecuteAsTemplate 是 Hugo 资源管道&…

2026/9/19 21:42:45 阅读更多 →
F12开发者工具完全指南:临时修改网页数据、下载视频与常见问题排查

F12开发者工具完全指南:临时修改网页数据、下载视频与常见问题排查

F12这个键,在大多数普通用户眼里就是个摆设,偶尔按一下还以为电脑坏了。但在我们这帮天天跟网页打交道的人手里,它简直就是一扇通往浏览器内部世界的后门——按一下,页面瞬间“解剖”给你看,哪里不满意改哪里&#xff…

2026/9/19 21:42:45 阅读更多 →
NPM安装配置完全指南:从Node.js环境搭建到高频报错排查

NPM安装配置完全指南:从Node.js环境搭建到高频报错排查

开头先聊点实在的。NPM这玩意儿,做过前端的朋友没有不知道的,但每次换电脑、重装系统、入职新公司配环境,总能看到一片哀嚎——报错千奇百怪,配置五花八门。2025年了,Node.js都迭代到20几版本了,NPM安装和配置依然是个经典问题。这篇文章我不打算照搬官方文档,而是把这几年来实…

2026/9/19 21:42:45 阅读更多 →
Flutter cli_tools移植鸿蒙:命令中继总线与终端控制台适配

Flutter cli_tools移植鸿蒙:命令中继总线与终端控制台适配

Flutter 三方的 cli_tools 这套库,最近被我整个搬到了鸿蒙设备上跑。标题写得挺长,什么“终端级生态系统底层适配”“命令解析中继总线”“设备控制台隔离界”,拆开讲其实就是一件事:让终端命令行那套输入、解析、回显、控制的交互…

2026/9/19 21:42:45 阅读更多 →
快递管理系统可行性分析:业务量测算、成本模型与技术选型

快递管理系统可行性分析:业务量测算、成本模型与技术选型

简介:一份面向高校计算机、物流管理相关专业学生及企业信息化规划人员的快递管理系统可行性分析报告。全篇以物流信息化为背景,围绕建设目标、技术条件、经济效益、法规政策、人力资源五大维度展开论证,既梳理了GPS、EDI、管理信息系统等现代…

2026/9/19 21:41:45 阅读更多 →

日新闻

BP神经网络时序预测:滑窗长度与多窗口平均策略

BP神经网络时序预测:滑窗长度与多窗口平均策略

简介:面向机器学习、深度学习与数据建模学习者的一份完整研究文献,聚焦BP神经网络在农业产量预测中的应用。文档以1980—2018年全国棉花产量为样本,系统讲解数据归一化处理、激活函数原理、多层神经网络结构搭建及训练流程,展示敏…

2026/9/19 0:00:30 阅读更多 →
Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

Transformer训练实时监控实战:基于MindSpore的损失曲线可视化方案

上个月调一个Deformable DETR模型,在单卡上要跑将近两天。第二天早上我下意识打开终端翻日志,发现loss从凌晨两点就开始往上爬,一路从0.8涨到1.35,整整六个小时没人发现。那六个小时的训练不仅白跑,还霸占着卡——等于…

2026/9/19 0:00:30 阅读更多 →
OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南

OpenCloud 中的 Go 类型安全转换库 spf13/cast:从零值回退到泛型 API 的完整实战指南 【免费下载链接】opencloud 🌤️ OpenCloud is the open source platform for file management, sharing and collaboration. Simple and sovereign. 项目地址: htt…

2026/9/19 0:00:30 阅读更多 →

周新闻

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验

AI SDK Harness 依赖更新指南:掌握 harness 包 SDK 依赖的升级、桥接同步与一致性校验 【免费下载链接】ai The AI Toolkit for TypeScript. From the creators of Next.js, the AI SDK is a free open-source library for building AI-powered applications and ag…

2026/9/19 3:59:36 阅读更多 →
Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化

Refine v5 Ant Design NumberField 组件实战:基于 Intl 的本地化数字格式化 【免费下载链接】refine A React Framework for building internal tools, admin panels, dashboards & B2B apps with unmatched flexibility. 项目地址: https://gitcode.com/GitH…

2026/9/19 3:53:08 阅读更多 →
Flutter应用改名全指南:从Android到iOS的配置与工具实践

Flutter应用改名全指南:从Android到iOS的配置与工具实践

刚接一个外包项目时,甲方要求把工程里临时用的应用名改成正式产品名。我本来觉得“改名”这种小事,打开配置文件改一行不就完了?结果真动手才发现,Flutter项目里“应用名称”根本不是一处配置,而是一整套散落在 Androi…

2026/9/19 4:02:43 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/16 22:31:27 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/19 17:50:38 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/16 22:32:59 阅读更多 →