整理的算法模板合集: ACM模板

点我看算法全家桶系列!!!

实际上是一个全新的精炼模板整合计划


Problem

给定一棵点带权无根树,对于每个 k∈[1,2×105]k\in[1,2\times10^5]k∈[1,2×105],求出有多少个无序点对 (x,y)(x,y)(x,y) 满足 xxx 到 yyy 的简单路径(链)上的所有节点的点权的 gcd⁡\gcdgcd 等于 kkk。(点对中的 xxx 可以等于 yyy,即单点也算作一个答案)

1≤n,ai≤2×1051\le n,a_i\le 2\times 10^51≤n,ai​≤2×105

Input

3
1 2 3
1 2
2 3

Output

1 4
2 1
3 1

Solution

定义树上 gcd⁡(x,y)\gcd(x,y)gcd(x,y) 表示 从点 xxx 到点 yyy 之间的简单路径(链)经过的所有点的点权的 gcd⁡\gcdgcd。

设 ans=f(k)ans=f(k)ans=f(k) ,其中 f(n)f(n)f(n) 表示题目中想要求的树上所有 gcd⁡(x,y)=n\gcd(x,y)=ngcd(x,y)=n 的点对 (x,y)(x,y)(x,y) 的数量。显然有些难以下手,因为这里求的是 gcd⁡=n\gcd=ngcd=n,已经固定了,也就是说我们需要算出所有的 gcd⁡\gcdgcd,显然是 O(n2)O(n^2)O(n2) 的复杂度。

树上问题比较抽象,不能很简练的列举出数学公式,考虑 gcd⁡\gcdgcd 计数问题尝试直接使用莫比乌斯反演公式解决。我们构造函数 F(n)=∑n∣df(d)F(n)=\sum\limits_{n\mid d}f(d)F(n)=n∣d∑​f(d)
显然 F(n)F(n)F(n) 的实际含义为 n∣gcd⁡(x,y)n\mid\gcd(x,y)n∣gcd(x,y) 的点对 (x,y)(x,y)(x,y) 的数量,即所有简单路径(链)的 gcd⁡(x,y)\gcd(x,y)gcd(x,y) 中有因子 nnn 的点对的数量。

此时根据莫比乌斯反演公式有:

f(n)=∑n∣dF(d)μ(dn)f(n)=\sum_{n\mid d}F(d)\mu(\dfrac{d}{n}) f(n)=n∣d∑​F(d)μ(nd​)

因此我们只需要计算 F(i),i∈[1,max⁡{a[i]}]F(i),i\in[1,\max\{a[i]\}]F(i),i∈[1,max{a[i]}] ,然后 O(nlogn)O(nlogn)O(nlogn) 卷积计算 f(i)f(i)f(i) 即可。(gcd⁡(x,y)≤max⁡(a[i])\gcd(x,y)\le \max(a[i])gcd(x,y)≤max(a[i]))

因为 F(n)F(n)F(n) 的含义为所有简单路径(链)的 gcd⁡(x,y)\gcd(x,y)gcd(x,y) 中有因子 nnn 的点对的数量,所以我们可以从因子的角度出发,求出所有点权的因子,因为点对 (x,y)(x,y)(x,y) 中 xxx 可以等于 yyy,所以 F(因子)++ ,然后对于所有的因子建分层图,每次处理一个因子。

对于因子 xxx,我们将 n−1n-1n−1 条边 (u,v)(u,v)(u,v) 中所有 gcd⁡(a[u],a[v])\gcd(a[u],a[v])gcd(a[u],a[v]) 含有因子 xxx 的边一起构建成一个分层图里,则该分层图中的所有边均有因子 xxx,在建图连边的过程中,对于两条链(连通块) A,BA,BA,B,我们需要计算有多少个点对,所以可以用并查集维护每个连通块的点的个数 size,使用并查集将他们连起来的时候,F(x)F(x)F(x) 得到的新的贡献(新的点对)显然为 size[A]×size[B]size[A]\times size[B]size[A]×size[B](AAA 中每一个点均可在 BBB 中任意选择一个点凑成一个新的点对)。对于所有因子执行这一过程,我们就可以计算出所有的 F(i)F(i)F(i)。

最后分析一下复杂度:1∼2×1051\sim 2\times 10^51∼2×105 中约数最多仅有 160160160 个,即每条边最多会在 160160160 个分层图里出现,我们先对每条边分解因子然后构建分层图,然后再枚举分层图使用并查集建图,复杂度为 O(n×max⁡{160,n})O(n\times \max\{160, \sqrt{n}\})O(n×max{160,n​})

Code

// Problem: G. GCD Counting
// Contest: Codeforces - Educational Codeforces Round 45 (Rated for Div. 2)
// URL: https://codeforces.com/problemset/problem/990/G
// Memory Limit: 256 MB
// Time Limit: 4500 ms
//
// Powered by CP Editor (https://cpeditor.org)#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 7, M = 2e3 + 7;int n, m, k, t;
int a[N];
int primes[N], cnt, mu[N];
bool vis[N];
int fa[N], siz[N];
ll f[N], F[N];
int u[N], v[N];
int maxx;
vector <int> c[N];template <typename T> inline void read(T& t) {int f = 0, c = getchar(); t = 0; while (!isdigit(c)) f |= c == '-', c = getchar();while (isdigit(c)) t = t * 10 + c - 48, c = getchar();if (f) t = -t;
} template <typename T> void print(T x) {if (x < 0) x = -x, putchar('-');if (x > 9) print(x / 10);putchar(x % 10 + 48);
} void init(int n)
{vis[1] = 1; mu[1] = 1;for(int i = 1; i <= n; ++ i) {if(vis[i] == 0) {primes[ ++ cnt] = i;mu[i] = -1;}for(int j = 1; j <= cnt && i * primes[j] <= n; ++ j) {vis[i * primes[j]] = 1;if(i % primes[j] == 0) {mu[i * primes[j]] = 0;break;}mu[i * primes[j]] -= mu[i];}}
}int Find(int x)
{if(fa[x] == x) return x;return fa[x] = Find(fa[x]);
}void Union(int d, int x, int y)
{int fx = Find(x);int fy = Find(y);if(fx == fy) return ;F[d] += 1ll * siz[fx] * siz[fy];fa[fx] = fy;siz[fy] += siz[fx];
}signed main()
{init(N - 7);read(n);for(int i = 1; i <= n; ++ i) {read(a[i]);maxx = max(maxx, a[i]);int x = a[i];for(int j = 1; j * j <= x; ++ j) {if(x % j == 0) {F[j] ++ ;if(j * j != x) F[x / j] ++ ;}} }/*for(int i = 1; i <= 2e5; ++ i) {if(F[i]) cout << F[i] << endl;}*/for(int i = 1; i <= n - 1; ++ i) {int x, y;read(x), read(y); u[i] = x, v[i] = y;int gcd = __gcd(a[x], a[y]);for(int j = 1; j * j <= gcd; ++ j) {if(gcd % j == 0) {c[j].push_back(i);if(j * j != gcd) c[gcd / j].push_back(i);}} }int limit = 2e5;for(int i = 1; i <= limit; ++ i) {for(int j = 0; j < c[i].size(); ++ j) {fa[u[c[i][j]]] = u[c[i][j]];siz[u[c[i][j]]] = 1;fa[v[c[i][j]]] = v[c[i][j]];siz[v[c[i][j]]] = 1;}for(int j = 0; j < c[i].size(); ++ j) {Union(i, u[c[i][j]], v[c[i][j]]);}}for(int i = 1; i <= limit; ++ i) {for(int j = i; j <= limit; j += i) {f[i] += 1ll * F[j] * mu[j / i];} } for(int i = 1; i <= limit; ++ i) {if(f[i]) {print(i);putchar(' ');print(f[i]);puts("");}}return 0;
}

CF990G GCD Counting(树上莫比乌斯反演,分层图,并查集)相关推荐

  1. java并查集找朋友圈_图—并查集(解决朋友圈问题)

    图也是一种 非线性结构,是由多个顶点组成的关系集合组成的一种数据结构.图可以分为两种,无向图和有向图. ★图的定义: ★典型问题: 利用图能够解决很多问题,这里有一个较为典型的问题,假如已知有n个人和 ...

  2. 【Project Euler】530 GCD of Divisors 莫比乌斯反演

    [题目]GCD of Divisors [题意]给定f(n)=Σd|n gcd(d,n/d)的前缀和F(n),n=10^15. [算法]莫比乌斯反演 [题解]参考:任之洲数论函数.pdf 这个范围显然 ...

  3. 数学--数论--HDU 4675 GCD of Sequence(莫比乌斯反演+卢卡斯定理求组合数+乘法逆元+快速幂取模)

    先放知识点: 莫比乌斯反演 卢卡斯定理求组合数 乘法逆元 快速幂取模 GCD of Sequence Alice is playing a game with Bob. Alice shows N i ...

  4. 牛客 - 牛半仙的妹子图(并查集+bitset/克鲁斯卡尔重构树+主席树)

    题目链接:点击查看 题目大意:给出一个由 n 个点和 m 条边组成的连通图,每个点都有一种颜色,每条边都有一个权值,现在规定一个起点 st,再给出 q 次询问,每次询问给出区间 [ l , r ] , ...

  5. CF650E Clockwork Bomb(树上构造类问题、并查集)

    Description 给出两棵 n 结点的有标号树. 每次操作删去第一棵树的一条边,再加上一条边,需要保证此时还是一棵树. 构造一种操作序列,将第一棵树变成第二棵树,使得操作数最小. n ≤ 5×1 ...

  6. 杭电1232(图—并查集)

    畅通工程 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submi ...

  7. BZOJ 3930 Luogu P3172 选数 (莫比乌斯反演)

    BZOJ 3930 Luogu P3172 选数 (莫比乌斯反演) 手动博客搬家:本文发表于20180310 11:46:11, 原地址https://blog.csdn.net/suncongbo/ ...

  8. 【算法训练营】 - ⑩ 并查集与图

    [算法训练营] - ⑩ 并查集与图 并查集 并查集特征 并查集的优化 图 图结构的表达 图的面试题如何搞定? 图的数据结构 点 边 图 生成图 图算法 广度优先遍历 深度优先遍历 图的拓扑排序算法 最 ...

  9. 牛客挑战赛51 E NIT的gcd(欧拉反演,建图优化,三元环计数)

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Problem 给你一个正整数 nnn. 请你输出 ∑i=1n∑j=1n∑k=1ngcd⁡(i,j)g ...

最新文章

  1. window下python扩展包大全
  2. SharePoint 2007/2010 的SPGridView 控件常见的两个问题
  3. 循环神经网络 (RNN)
  4. Codeforces 1188E Problem from Red Panda (计数)
  5. 人身三流指什么_电气隔离是什么意思呢?
  6. Boost:glob测试程序
  7. 我的Linux系统入坑之路!!!!
  8. ubuntu安装jdk,ubuntu设置java环境变量
  9. [C++11]lambda表达式语法
  10. Ubuntu16.04通过GPT挂载硬盘
  11. java如何关闭一个线程_如何关闭一个java线程池
  12. 混合精度训练amp,torch.cuda.amp.autocast():
  13. AudioRecord 采集音频PCM数据
  14. C常用的字符串函数实现
  15. shell脚本学习(3)文件判断
  16. carbon----代码美化工具
  17. K核苷酸频率(KNF,k-nucleotide frequencies)或K-mer频率
  18. Unity问题(1)——mesh法线反转
  19. 品质担当,有效提升办公生产力,永艺XY人体工学椅开箱实测
  20. 任意进制加法计数器电路设计

热门文章

  1. 图像分类和目标检测技术有什么区别?
  2. 基于DQN强化学习训练一个超级玛丽
  3. 什么是 Canny 边缘检测算法?
  4. Multisim 12.0 笔记
  5. 2017年5个最佳网络监控工具 你知道哪些
  6. jquery each
  7. Why HashMap Extends AbstractMap and Implement Map
  8. shell 读取配置文件
  9. 带权重的随机输出数组中的元素
  10. 设计模式----单件模式(c++)