[ABC248G] GCD cost on the tree
Problem Statement
You are given an undirected tree with $N$ vertices.
Let us call the vertices Vertex $1$, Vertex $2$, $\ldots$, Vertex $N$. For each $1\leq i\leq N-1$, the $i$-th edge connects Vertex $U_i$ and Vertex $V_i$.
Additionally, each vertex is assigned a positive integer: Vertex $i$ is assigned $A_i$.
The cost between two distinct vertices $s$ and $t$, $C(s,t)$, is defined as follows.
Let $p_1(=s)$, $p_2$, $\ldots$, $p_k(=t)$ be the vertices of the simple path connecting Vertex $s$ and Vertex $t$, where $k$ is the number of vertices in the path (including the endpoints).
Then, let $C(s,t)=k\times \gcd (A_{p_1},A_{p_2},\ldots,A_{p_k})$,
where $\gcd (X_1,X_2,\ldots, X_k)$ denotes the greatest common divisor of $X_1,X_2,\ldots, X_k$.
Find $\displaystyle\sum_{i=1}^{N-1}\sum_{j=i+1}^N C(i,j)$, modulo $998244353$.
Constraints
- $2 \leq N \leq 10^5$
- $1 \leq A_i\leq 10^5$
- $1\leq U_i<V_i\leq N$
- All values in input are integers.
- The given graph is a tree.
Input
Input is given from Standard Input in the following format:
$N$
$A_1$ $A_2$ $\cdots$ $A_N$
$U_1$ $V_1$
$U_2$ $V_2$
$\vdots$
$U_{N-1}$ $V_{N-1}$
Output
Print $\displaystyle\sum_{i=1}^{N-1}\sum_{j=i+1}^N C(i,j)$, modulo $998244353$.
Sample Input 1
4
24 30 28 7
1 2
1 3
3 4
Sample Output 1
47
There are edges directly connecting Vertex $1$ and $2$, Vertex $1$ and $3$, and Vertex $3$ and $4$.
Thus, the costs are computed as follows.
- $C(1,2)=2\times \gcd(24,30)=12$
- $C(1,3)=2\times \gcd(24,28)=8$
- $C(1,4)=3\times \gcd(24,28,7)=3$
- $C(2,3)=3\times \gcd(30,24,28)=6$
- $C(2,4)=4\times \gcd(30,24,28,7)=4$
- $C(3,4)=2\times \gcd(28,7)=14$
Thus, the sought value is $\displaystyle\sum_{i=1}^{3}\sum_{j=i+1}^4 C(i,j)=(12+8+3)+(6+4)+14=47$ modulo $998244353$, which is $47$.
Sample Input 2
10
180 168 120 144 192 200 198 160 156 150
1 2
2 3
2 4
2 5
5 6
4 7
7 8
7 9
9 10
Sample Output 2
1184
两个东西乘起来,很不好算。我们尝试拆开来算,就是枚举一个,求另一个的和。
路径数量和 gcd,看起来枚举gcd更容易。为了方便,设一个边 \((u,v)\) 的边权为 \(\gcd(a_u,a_v)\),这样也好加边。设现在枚举,令 \(k\) 为枚举到的最小公因数,一个很自然的想法就是把所有 \(a\) 为 \(k\) 的倍数的边拎出来,组成一棵树,然后跑一个 dp。考虑一条边 \((u,v,w)\),那么 \(w\) 的因数个数就是他会被计算的次数,因数个数 \(\sqrt{w}\) 个,所以如果能保证dp和建树是严格 \(O(n)\),最终复杂度是 \(O(n\sqrt{n})\)
先来看一下怎么dp。现在给出一棵树,我们要求所有路径长度之和。首先可以每个连通块单独考虑。定义 \(dp_i\) 为所有树上以 \(i\) 为端点的路径之和, \(c_i\) 为 \(i\) 为根的子树大小。那么 \(dp_v\) 转移到 \(dp_i\) 时,共有 \(c_v\) 个路径,他们长度全部增加1。算最终答案时,目前的 \(dp_i\) 会有多 \(c_v\) 个, \(dp_v\) 会多目前的 \(c_i\) 个。
但是我们发现这样算出来的答案不完全对。因为我们并不能保证这些路径的 \(\gcd\) 为 \(k\),只能保证他是 \(k\) 的倍数。我们可以用筛法处理出一个容斥系数。因为我在算 \(k\) 的答案一定算了 \(2k\) 的答案,在 \(2k\) 时容斥系数要减去那么多。
总复杂度 \(O(n\sqrt{n)\)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5,P=998244353;
int n,a[N],u[N],vis[N],e_num,hd[N],ret,ans,c[N],dp[N],p[N],fp[N],v[N];
struct edge{
int v,nxt;
}e[N<<1];
vector<int>g[N],f[N];
void add_edge(int u,int v)
{
e[++e_num]=(edge){v,hd[u]};
hd[u]=e_num;
}
int gcd(int x,int y)
{
if(!y)
return x;
return gcd(y,x%y);
}
void dfs(int x,int y)
{
// printf("%d %d\n",x,y);
vis[x]=0;
dp[x]=c[x]=1;
fp[x]=0;
for(int i=hd[x];i;i=e[i].nxt)
{
if(e[i].v==y)
continue;
dfs(e[i].v,x);
int ac=c[x],ad=dp[x];
int bc=c[e[i].v],bd=dp[e[i].v];
(fp[x]+=(1LL*ad*bc%P+1LL*ac*bd%P)%P)%=P;
(fp[x]+=fp[e[i].v])%=P;
(dp[x]+=(bc+bd)%P)%=P;
(c[x]+=bc)%=P;
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",a+i);
for(int i=1;i<N;i++)
for(int j=1;j*i<N;j++)
g[i*j].push_back(i);
for(int i=1;i<n;i++)
{
scanf("%d%d",u+i,v+i);
int w=gcd(a[u[i]],a[v[i]]);
for(int j=0;j<g[w].size();j++)
f[g[w][j]].push_back(i);
}
for(int i=1;i<N;i++)
{
p[i]+=i;
for(int j=2;1LL*j*i<N;j++)
p[j*i]-=p[i];
e_num=0;
for(int j=0;j<f[i].size();j++)
{
int x=u[f[i][j]],y=v[f[i][j]];
add_edge(x,y);
add_edge(y,x);
vis[x]=vis[y]=1;
}
for(int j=0;j<f[i].size();j++)
{
int x=u[f[i][j]];
if(vis[x])
{
dfs(x,0);
(ans+=(1LL*fp[x]%P*p[i]%P))%=P;
}
}
for(int j=0;j<f[i].size();j++)
{
int x=u[f[i][j]],y=v[f[i][j]];
hd[x]=hd[y]=0;
}
// for(int i=1;i<=n;i++)
// printf("%d ",fp[i]);
// putchar('\n');
}
printf("%d",ans);
}
[ABC248G] GCD cost on the tree的更多相关文章
- Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】
传送门:http://codeforces.com/contest/1092/problem/F F. Tree with Maximum Cost time limit per test 2 sec ...
- CF1092 --- Tree with Maximum Cost
CF1324 --- Maximum White Subtree 题干 You are given a tree consisting exactly of \(n\) vertices. Tree ...
- POJ3013 Big Christmas Tree[转换 最短路]
Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 23387 Accepted: 5 ...
- Color a Tree[HDU1055]
Color a Tree Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Tota ...
- poj 3013 Big Christmas Tree (最短路径Dijsktra) -- 第一次用优先队列写Dijsktra
http://poj.org/problem?id=3013 Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total S ...
- poj 3013 Big Christmas Tree
Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 20974 Accepted: 4 ...
- Big Christmas Tree(poj-3013)最短路
Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total Submissions: 25823 Accepted: 5 ...
- hdu-3071 Gcd & Lcm game---质因数分解+状态压缩+线段树
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3071 题目大意: 给定一个长度为n的序列m次操作,操作的种类一共有三种 查询 L :查询一个区间的所 ...
- HDU 2196 Computer 树形DP 经典题
给出一棵树,边有权值,求出离每一个节点最远的点的距离 树形DP,经典题 本来这道题是无根树,可以随意选择root, 但是根据输入数据的方式,选择root=1明显可以方便很多. 我们先把边权转化为点权, ...
- HDU 5861 Road (线段树)
Road 题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5861 Description There are n villages alo ...
随机推荐
- java与es8实战之一:以builder pattern开篇
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于<java与es8实战>系列 < ...
- 【LaTeX】环境配置以及中文支持
目录 网页环境 Overleaf 本地环境 TeX Live TeXstudio VSCode 安装 LaTeX Workshop 扩展 编译链配置 正向同步 反向同步 其他可选配置 中文支持 XeL ...
- MindSponge分子动力学模拟——计算单点能(2023.08)
技术背景 在前面的几篇文章中,我们分别介绍了MindSponge的软件架构.MindSponge的安装与使用和如何在MindSponge中定义一个分子系统.那么就像深度学习中的损失函数,或者目标函数, ...
- 每天一道面试题:Spring的Bean生命周期
Spring的Bean生命周期包括以下步骤: 1.实例化(Instantiation):当Spring容器接收到创建Bean的请求时,它会先实例化Bean对象.这个过程可以通过构造函数.工厂方法或者反 ...
- MindSponge分子动力学模拟——Constraint约束
技术背景 在前面的几篇博客中,我们已经介绍了MindSponge的基本使用方法,比如定义一个分子系统.计算分子的单点能以及迭代器的使用等.有了这些基础的教程,用户以及可以执行一些比较简单的模拟任务,比 ...
- Vue3中的几个坑,你都见过吗?
Vue3 目前已经趋于稳定,不少代码库都已经开始使用它,很多项目未来也必然要迁移至Vue3.本文记录我在使用Vue3时遇到的一些问题,希望能为其他开发者提供帮助. 1. 使用reactive封装基础数 ...
- numpy 索引,切片 ,转置,变值,多个数组的拼接
- 4.Autofac依赖注入初使用
前面几篇文章只是初步搭建项目结构,那到底能否运行呢?(能是肯定的啦) 毕竟咱都NetCore了,所以依赖注入要搞起来.专业的解释我就不多说了,很多博客文章说的很详细(其实是我忘了那些术语怎么讲). 按 ...
- pandas -- DataFrame的级联以及合并操作
博客地址:https://www.cnblogs.com/zylyehuo/ 开发环境 anaconda 集成环境:集成好了数据分析和机器学习中所需要的全部环境 安装目录不可以有中文和特殊符号 jup ...
- jquery设置图片可手动拖拽
JQuery是一款流行的JavaScript框架,可以轻松实现网页交互效果.而其中一种常见效果是图片手动拖拽.以下是设置图片手动拖拽的JQuery代码. 1 2 3 4 5 6 7 8 9 10 11 ...