当前位置: 首页 > news >正文

贡献法+容斥原理,abc248G - GCD cost on the tree

目录

一、题目

1、题目描述

2、输入输出

2.1输入

2.2输出

3、原题链接

二、解题报告

1、思路分析

2、复杂度

3、代码详解


一、题目

1、题目描述

2、输入输出

2.1输入

2.2输出

3、原题链接

https://atcoder.jp/contests/abc248/tasks/abc248_g


二、解题报告

1、思路分析

考虑 f(x) 为 gcd 恰为 x 的路径长度和,g(x) 为 gcd 为 x 的倍数的路径长度和

那么 f(x) = g(x) - Σ f(y),y = 2x, 3x....

由于[1, 1E5] 中,每个数的约数个数最大为一百多,那么我们考虑对每个数做因子分解,保存所有因子被包含在A[i] 的下标i

那么我们枚举 gcd(path) 的倍数g,跑树形dp,计算由点权为 g 的倍数的点 构成的路径总数,这是经典的贡献法,对于一条边<u, v>,在所有路径出现次数是 (树的大小 - siz[v]) * siz[v]

因为题目路径长度定义为点权,所以对于每个 g 的倍数构成的子树,我们需要额外加上一个组合数

最终答案为 Σxf(x)

2、复杂度

时间复杂度: O(d(V) * n),d(V) 为 [1, V] 最大约数个数,V = 1E5,空间复杂度:O(n + Vd(V))

3、代码详解

#include <bits/stdc++.h> namespace ranges = std::ranges; namespace views = std::views; using i64 = long long; constexpr int M = 1E5; constexpr int P = 998244353; int add(int x, int y) { x += y - P; x += (x >> 31) & P; return x; } int mul(int x, int y) { return 1LL * x * y % P; } std::vector<int> fac[M + 1], st[M + 1]; int f[M + 1]; int main() { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); for (int i = 1; i <= M; ++i) { for (int j = i; j <= M; j += i) { fac[j].push_back(i); } } int N; std::cin >> N; std::vector<int> A(N); for (int i = 0; i < N; ++i) { std::cin >> A[i]; for (int x : fac[A[i]]) { st[x].push_back(i); } } std::vector<std::vector<int>> adj(N); for (int i = 1; i < N; ++i) { int u, v; std::cin >> u >> v; --u; --v; adj[u].push_back(v); adj[v].push_back(u); } std::vector<bool> vis(N); std::vector<int> siz(N), val; auto dfs = [&](this auto &&self, int u, int g) -> void { siz[u] = 1; vis[u] = true; for (int v : adj[u]) { if (vis[v] || A[v] % g > 0) { continue; } self(v, g); siz[u] += siz[v]; val.push_back(siz[v]); } }; for (int g = 1; g <= M; ++g) { for (int i : st[g]) { vis[i] = false; } for (int i : st[g]) { if (!vis[i]) { val.clear(); dfs(i, g); for (int x : val) { f[g] = add(f[g], mul(siz[i] - x, x)); } f[g] = add(f[g], 1LL * siz[i] * (siz[i] - 1) / 2 % P); } } } int ans = 0; for (int g = M; g > 0; --g) { for (int x = g + g; x <= M; x += g) { f[g] = add(f[g], P - f[x]); } ans = add(ans, mul(f[g], g)); } std::cout << ans << '\n'; return 0; }
http://www.jsqmd.com/news/449535/

相关文章:

  • 亲测分享权威geo渠道实践经验
  • 人工智能+AI的微信小程序 高校新生报到管理系统
  • 广度看偏好、深度看对错——Mix-GRM 用 8B 模型打败一众开源奖励模型
  • c语言函数的学习记录
  • 2026年文本转语音软件深度测评:从新手到专业,这6款不踩坑
  • Qwen3-ASR-0.6B效果对比:相同音频下比Whisper-small快2.7倍,CER低1.8%
  • 前后端分离榆林特色旅游网站系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程
  • Solidity 智能合约进阶 2| 安全性和验证 验证签名
  • kuka库卡机器人示教器花屏维修
  • 2026国内心理咨询APP权威测评榜单重磅发布
  • 在线小说阅读平台信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
  • Lychee-rerank-mm模型解释性分析:理解多模态重排序的决策过程
  • Qwen-Image-2512-SDNQ MATLAB下载安装集成:科研工作流优化
  • CMake 项目构建指南:从基础到跨平台动态库导出
  • 教你从0基础学AI大模型【大四AI学长的开篇自白】
  • 记录每天的学习内容2026.3.7--了解CNN的发展历程和技术迭代(AI总结),与ai问答全部对话在https://github.com/101per/learning.git
  • Linux 系统内核参数优化配置入门
  • 分布式电源接入配电网:电压与网损的奇妙变化之旅
  • 手把手教程:用EVA-01分析游戏UI,自动识别功能模块与新手引导
  • Wan2.2-T2V-A5B提示词工程:借鉴Java设计模式的思想构建可复用模板
  • 别再无脑用 `JSON.parse()` 了!这个安全漏洞你可能每天都在触发
  • 人工智能+AI的生鲜农产品保鲜及溯源商城管理系统vue
  • VulnHub DC-5 靶机渗透测试笔记
  • 使用CGAL的半边数据结构HalfedgeDS_list构建一个立方体
  • ez-rce
  • [AI-Talk] OpenClaw如何实现直播评论
  • AI助教新实践:Nanbeige 4.1-3B实现自动化作业批改与反馈
  • 人工智能+AI的微信小程序的考研交流系统
  • nanobot效果展示:Qwen3-4B在Chainlit中解析图片URL、执行shell命令案例
  • CosyVoice-300M Lite应用分享:无障碍服务中的语音导航实现