首页 > 其他分享 >GCD Counting题解

GCD Counting题解

时间:2023-09-02 10:33:25浏览次数:40  
标签:le GCD int 题解 点权 times Trick Counting gcd

题意

有一棵有 \(n\) 个节点的树,第 \(i\) 个节点有点权 \(a_i\)。

定义 \(g(x,y)\) 为 \(x\) 到 \(y\) 的树上路径所经过的点的点权 \(\gcd\)。

对于每一个正整数 \(k\in[1,2\times 10^5]\) 求出满足以下条件的 \(x,y\) 的对数:

  • \(1\le x\le y\le n\)

  • \(g(x,y)=k\)

\(1\le n,a_i\le 2\times 10^5\)

Trick 1

显然 \(gcd(x,y)=k\) 是非常难求的,所以我们考虑用莫比乌斯反演,令 \(F(i)\) 表示 \(gcd(x,y)=k\) 的点对个数 \(G(i)\) 表示 \(gcd(x,y)\) 是 \(k\) 的倍数的点对个数。很明显,求出所有 \(G(i)\) 就可以求出所有 \(F(i)\),即:

\[F(i)=\sum\limits_{i|d}\mu(\frac{d}{i})G(d) \]

Trick 2

考虑求 \(G(i)\)。枚举两端的点权都是 \(i\) 的边,合并两个点,最后计算每个联通块内的点数,任意两个点都是一个合法的点对,所以是 \(x\times (x-1)/2\),\(x\) 为连通块中点的数量。每条边最多被算 \(160\) 次,即当 \(gcd(u,v)=166320=2^4×3^3×5×7×11\) 时,他有 \(160\) 个因数,他的每个因数都会枚举这条边,但它是小于 \(2e5\) 的拥有最多因数的数,所以枚举 \(G(i)\) 的时间复杂度不超过 \(O(160m)\)

Trick 3

考虑倒着求 \(F(i)\),很明显当求到 \(F(i)\) 时,所有满足 \(j>i\) 的\(F(j)\) 都已经求出来,那么就会有:

\[F(i)=G(i)-\sum\limits_{i|d}F(d) \]

就不用求 \(\mu\) 了

细节:

因为形如 \((i,i)\) 的点对是合法的,所以在输出答案 \(F(i)\) 时还要加上点权为 \(i\) 的点的个数

上代码:

#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;
}

标签:le,GCD,int,题解,点权,times,Trick,Counting,gcd
From: https://www.cnblogs.com/pengchujie/p/17673295.html

相关文章

  • CF915G Coprime Arrays 题解
    题意给定\(n,k\),对于所有的\(m\in\left[1,k\right]\),求长度为\(n\),值域为\(\left[1,m\right]\)且最大公约数为\(1\)的序列种数,对\(10^9+7\)取模。(\(1\len,k\le2\times10^6\))。题解设\(f(d,m)\)表示长度为\(n\),值域为\(\left[1,m\right]\)且最大......
  • [NOI2021] 轻重边题解
    题目传送门一眼数据结构考虑树上有什么数据结构支持\(x\)到\(y\)节点的修改和查询,那就是:树链剖分。那么这道树链剖分的题有个\(trick\):边点转换&染色法,对于每次修改,考虑将修改路径上的点全部染上一种独一无二的颜色,而查询的时候,就查询路径上相邻的相同的颜色节点个数即可......
  • 爱思创模拟06试题易错题解析
    错误原因:漏项正确答案:C按节点数分类穷举 举一反三:  错误原因:处理三个空位的时候,情况考虑的太多正确答案:分情况计算,先枚举4个人共A(4,4)=24种情况,再考虑剩下两个空位置的情况,即A(5,2)=20种情况,最终答案就是24*20=480种举一反三:  错误原因:不会计算时间复杂度......
  • 题解 正妹吃月饼
    题目链接由于每个质量的月饼只有一个,并且质量恰好是2的整数倍,所以考虑将一个质量看成一个二进制位。那么也就是说,我们要构造一个二进制数\(x\),使得\(x\)的\(1\)的个数最多,且满足\(a\lex\leb\)。那么这就可以用类似数位\(DP\)的思路来做,从高位往低位看,若\(a_i=b_i=1......
  • NOIP2012提高组初赛易错题解析
    一.3. 错误原因:忘记了解析:Intel是全球最大的CPU厂商,AMD是世界上首个研发出7纳米CPU的厂商 6.错误原因:忘记了解析:ENIAC是世界上首台计算机,属于第一代计算机,即电子管计算机 10.错误原因:选项理解错误解析:A由蝙蝠,发明雷达是正确的,B因特网的发明与蜘蛛网无关,只是形......
  • NOIP2011提高组初赛易错题解析
    一.7.错误原因:不知道解析:快速排序在理论上最低的时间复杂度为O(n),但实际最低的时间复杂度为O(nlogn) 二.1.错误原因:漏项了解析:这棵树最少有12层,但题目是问可能是几层,所以还可能是2011层 5.错误原因:漏了一种情况解析:这道题的树有两种,所以答案也有两种 ......
  • 牛客小白月赛77 C题解 | 小Why的商品归位
    原题链接先不考虑车子的容量问题,因为结束位置保证是在起始位置之后的,那我们从前往后扫,发现是可以知道每个点时的车内的商品。但是现在有了容量限制,我们怎么办呢,如果对于一段,k都是大于每个点的货物量时,可以一趟装完,但是如果大于k就需要不知一次,可以发现所需的其实是该段的最大......
  • CF1626F A Random Code Problem 题解
    题意给定长度为\(n\)的数组\(a\)和一个整数\(k\),执行下面的代码:longlongans=0;//定义一个初始值为0的长整型变量for(inti=1;i<=k;i++){ intidx=rnd.next(0,n-1);//生成一个介于0到n-1的随机数(含0和n-1) //每个数被选中的概率是相同的 an......
  • Maximum Diameter 题解
    MaximumDiameter题目大意定义长度为\(n\)的序列\(a\)的权值为:所有的\(n\)个点的第\(i\)个点的度数为\(a_i\)的树的直径最大值,如果不存在这样的树,其权值为\(0\)。给定\(n\),求所有长度为\(n\)的序列的权值和。思路分析\(n\)个点的树的边数为\(n-1\),总度数......
  • 【题解】Harbour.Space Scholarship Contest 2023-2024 D,E,F(CF1864)
    D.MatrixCascade题目描述:有一个大小为\(n\timesn\)的矩阵,由0和1组成。行的编号从上到下依次为\(1\)到\(n\),列的编号从左到右依次为\(1\)到\(n\)。第\(x\)行与第\(y\)列交叉处的单元格记为\((x,y)\)。水月想把矩阵的所有元素都变成0。她可以一步完成以下操作:选择任意......