尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

DeepSeek LeetCode 3336. 最大公约数相等的子序列数量 Java实现

DeepSeek    LeetCode 3336. 最大公约数相等的子序列数量 Java实现
📅 发布时间:2026/6/21 1:26:16

根据搜索结果,LeetCode 3336 有两种主流解法,这里提供对应的 Java 实现及说明。

方法一:多维 DP(记忆化搜索)

这种解法最直观,用“选或不选”的思维为每个元素做三种决策。

```java
class Solution {
private static final int MOD = 1_000_000_007;
private int[][][] memo;
private int[] nums;

public int subsequencePairCount(int[] nums) {
int n = nums.length;
this.nums = nums;
// 值域上限 200,多开一位存0(代表空序列的GCD)
memo = new int[n][201][201];
for (int i = 0; i < n; i++) {
for (int j = 0; j < 201; j++) {
Arrays.fill(memo[i][j], -1);
}
}
// 从第一个元素开始,两个子序列初始GCD均为0
// 最后 -1 是为了排除两个子序列同时为空的情况
return (dfs(0, 0, 0) - 1 + MOD) % MOD;
}

private int dfs(int i, int g1, int g2) {
if (i == nums.length) {
// 两个子序列都必须非空且GCD相等
return (g1 != 0 && g2 != 0 && g1 == g2) ? 1 : 0;
}
if (memo[i][g1][g2] != -1) return memo[i][g1][g2];

int x = nums[i];
// 三种决策:不选 / 放入第一个 / 放入第二个
long skip = dfs(i + 1, g1, g2);
long put1 = dfs(i + 1, gcd(g1, x), g2);
long put2 = dfs(i + 1, g1, gcd(g2, x));

long ans = (skip + put1 + put2) % MOD;
memo[i][g1][g2] = (int) ans;
return memo[i][g1][g2];
}

private int gcd(int a, int b) {
while (b != 0) {
int tmp = a % b;
a = b;
b = tmp;
}
return a;
}
}
```

方法二:倍数容斥 AC

利用值域(≤200)和容斥原理优化计数,性能更优。

```java
class Solution {
private static final int MOD = 1_000_000_007;
private static final int MX = 201;
private static int[][] lcms = new int[MX][MX];
private static long[] pow2 = new long[MX];
private static long[] pow3 = new long[MX];
private static int[] mu = new int[MX];

static {
// 预处理:LCM、2/3的幂、莫比乌斯函数
for (int i = 1; i < MX; i++) {
for (int j = 1; j < MX; j++) {
lcms[i][j] = lcm(i, j);
}
}
pow2[0] = pow3[0] = 1;
for (int i = 1; i < MX; i++) {
pow2[i] = pow2[i-1] * 2 % MOD;
pow3[i] = pow3[i-1] * 3 % MOD;
}
mu[1] = 1;
for (int i = 1; i < MX; i++) {
for (int j = i*2; j < MX; j += i) {
mu[j] -= mu[i];
}
}
}

public int subsequencePairCount(int[] nums) {
int m = Arrays.stream(nums).max().orElse(0);
int[] cnt = new int[m+1];
for (int x : nums) cnt[x]++;

// cnt[i]:nums中i的倍数的个数
for (int i = 1; i <= m; i++) {
for (int j = i*2; j <= m; j += i) {
cnt[i] += cnt[j];
}
}

// f[g1][g2]:粗略计数
long[][] f = new long[m+1][m+1];
for (int g1 = 1; g1 <= m; g1++) {
for (int g2 = 1; g2 <= m; g2++) {
int l = lcms[g1][g2];
int c = (l <= m) ? cnt[l] : 0;
int c1 = cnt[g1], c2 = cnt[g2];
long val = pow3[c] * pow2[c1 + c2 - 2*c] % MOD;
val = (val - pow2[c1] - pow2[c2] + 1) % MOD;
f[g1][g2] = (val + MOD) % MOD;
}
}

// 倍数容斥求精确答案
long ans = 0;
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= m/i; j++) {
for (int k = 1; k <= m/i; k++) {
ans += (long) mu[j] * mu[k] * f[j*i][k*i];
ans %= MOD;
}
}
}
return (int) ((ans % MOD + MOD) % MOD);
}

private static int gcd(int a, int b) {
while (b != 0) { int t = a % b; a = b; b = t; }
return a;
}
private static int lcm(int a, int b) {
return a / gcd(a, b) * b;
}
}
```

复杂度对比

· 多维 DP:O(n * 200 * 200) 时间与空间。
· 倍数容斥:O(m^3) 时间(m≤200),O(m^2) 空间。

相关新闻

  • 2026南通漏水检测维修本地口碑防水商家榜单:厨卫/阳台/屋面/地下室渗漏水维修,持证施工+明码实价,防水补漏公司TOP5推荐 - 即刻修防水
  • 2026李沧区专业的管道疏通公司推荐榜 - 品牌排行榜
  • 思维链与结构化 Prompt:大模型对话工程的深层优化实践

最新新闻

  • 终极指纹识别数据集指南:如何快速获取高质量生物特征数据
  • MaterialAlertDialog:Android中合规弹窗的实现原理与工程实践
  • SDN与机器学习融合:构建智能网络异常检测与自动化响应系统
  • 模型强化学习驱动双足机器人被动动力学:高效行走的算法与工程实践
  • 基于专家模型特征提取与分解的分类性能评估与提升实战
  • 多语言文本嵌入模型在仇恨言论检测中的性能评估与实战应用

日新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号