GCD Counting题解
题意
有一棵有
定义
对于每一个正整数
Trick 1
显然
Trick 2
考虑求
Trick 3
考虑倒着求
就不用求
细节:
因为形如
上代码:
#include<bits/stdc++.h> #define ll long long using namespace std; const int N=2e5+50; int n,a[N],u[N],v[N],tzy; vector<int> val[N]; int f[N],gs[N],f1,f2; bool vis[N]; ll G[N]; int find(int x) { if(f[x]==x) return x; return f[x]=find(f[x]); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<n;i++) { scanf("%d %d",&u[i],&v[i]); tzy=__gcd(a[u[i]],a[v[i]]); for(int j=1;j*j<=tzy;j++) { if(tzy%j) continue; val[j].push_back(i); if(j^(tzy/j)) val[tzy/j].push_back(i); } } for(int i=1;i<=n;i++) f[i]=i,gs[i]=1; for(int i=1;i<=N-50;i++) { for(int j=0;j<val[i].size();j++) { f1=find(u[val[i][j]]),f2=find(v[val[i][j]]); if(f1!=f2) { G[i]=G[i]-1ll*gs[f1]*(gs[f1]-1)/2-1ll*gs[f2]*(gs[f2]-1)/2; f[f1]=f2; gs[f2]+=gs[f1]; G[i]=G[i]+1ll*gs[f2]*(gs[f2]-1)/2; } } for(int j=0;j<val[i].size();j++) { f[u[val[i][j]]]=u[val[i][j]]; f[v[val[i][j]]]=v[val[i][j]]; gs[u[val[i][j]]]=1; gs[v[val[i][j]]]=1; } } for(int i=2e5;i>=1;i--) { for(int j=i+i;j<=2e5;j+=i) G[i]-=G[j]; } for(int i=1;i<=n;i++) G[a[i]]++; for(int i=1;i<=2e5;i++) if(G[i]) printf("%d %lld\n",i,G[i]); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现