CodeForces - 990G GCD Counting
Discription
You are given a tree consisting of nn vertices. A number is written on each vertex; the number on vertex ii is equal to aiai.
Let's denote the function g(x,y)g(x,y) as the greatest common divisor of the numbers written on the vertices belonging to the simple path from vertex xx to vertex yy(including these two vertices).
For every integer from 11 to 2⋅1052⋅105 you have to count the number of pairs (x,y)(x,y) (1≤x≤y≤n)(1≤x≤y≤n) such that g(x,y)g(x,y) is equal to this number.
Input
The first line contains one integer nn — the number of vertices (1≤n≤2⋅105)(1≤n≤2⋅105).
The second line contains nn integers a1a1, a2a2, ..., anan (1≤ai≤2⋅105)(1≤ai≤2⋅105) — the numbers written on vertices.
Then n−1n−1 lines follow, each containing two integers xx and yy (1≤x,y≤n,x≠y)(1≤x,y≤n,x≠y)denoting an edge connecting vertex xx with vertex yy. It is guaranteed that these edges form a tree.
Output
For every integer ii from 11 to 2⋅1052⋅105 do the following: if there is no pair (x,y)(x,y) such that x≤yx≤y and g(x,y)=ig(x,y)=i, don't output anything. Otherwise output two integers: iiand the number of aforementioned pairs. You have to consider the values of ii in ascending order.
See the examples for better understanding.
Examples
3
1 2 3
1 2
2 3
1 4
2 1
3 1
6
1 2 4 8 16 32
1 6
6 3
3 4
4 2
6 5
1 6
2 5
4 6
8 1
16 2
32 1
4
9 16 144 6
1 3
2 3
4 3
1 1
2 1
3 1
6 2
9 2
16 2
144 1 震惊,玄学做法竟然跑过了点分治。。。。
很显然,我们可以先求出g是i倍数的点对数ans[i],然后再反演出答案。
求g是i倍数的点对数的时候就调和级数枚举一下倍数,然后并查集一下就ojbk了。。。 虽然这种做法对于随机数据来说非常的强大,但是一遇到精心构造的数据就gg了,这就是窝一开始TLE的原因。。。
比如n个点的点权都是 <=2e5 的约数最多的数,那么上述做法的总运算次数大致是 O((n+m) * div * 反阿科玛函数),就凉凉了。。。 后来我加了一个比较强的剪枝就过了:
当所有点权都是i的倍数的时候,那就不做并查集,而是直接用 C(n+1,2) 减去 >i且是i倍数的J的ans... 感谢出题人不卡之恩2333
#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define pb push_back
const int maxn=200005; inline int read(){
int x=0; char ch=getchar();
for(;!isdigit(ch);ch=getchar());
for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return x;
} void W(ll x){ if(x>=10) W(x/10); putchar(x%10+'0');} int n,m,hd[maxn],ne[maxn*2],to[maxn*2],num,cnt[maxn];
int siz[maxn],dfn[maxn],dc,p[maxn],a[maxn];
vector<int> pt[maxn];
ll ans[maxn]; inline void add(int x,int y){ to[++num]=y,ne[num]=hd[x],hd[x]=num;} int getf(int x){ return p[x]==x?x:(p[x]=getf(p[x]));} inline void solve(){
for(int i=2e5,O;i;i--){
dc++,O=0; for(int j=i;j<=2e5;j+=i) O+=cnt[j],ans[i]-=ans[j]; if(O==n){
ans[i]+=n*(ll)(n+1)>>1;
continue;
} for(int j=i;j<=2e5;j+=i){ for(int l=pt[j].size()-1,now;l>=0;l--){
now=pt[j][l]; if(dfn[now]!=dc) dfn[now]=dc,p[now]=now,siz[now]=1,ans[i]++; for(int k=hd[now],fa,fb;k;k=ne[k]) if(dfn[to[k]]==dc){
fa=getf(now),fb=getf(to[k]); if(fa!=fb){
p[fb]=fa,ans[i]+=siz[fa]*(ll)siz[fb];
siz[fa]+=siz[fb];
}
}
}
}
}
} int main(){
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout); n=read();
for(int i=1;i<=n;i++) a[i]=read(),pt[a[i]].pb(i),cnt[a[i]]++; int uu,vv;
for(int i=1;i<n;i++)
uu=read(),vv=read(),add(uu,vv),add(vv,uu); solve(); for(int i=1;i<=2e5;i++) if(ans[i]) W(i),putchar(' '),W(ans[i]),puts("");
return 0;
}
CodeForces - 990G GCD Counting的更多相关文章
- cf 990G - GCD Counting
题意 #include<bits/stdc++.h> #define t 200000 #define MAXN 200100 using namespace std; int n; in ...
- Educational Codeforces Round 45 (Rated for Div. 2) G - GCD Counting
G - GCD Counting 思路:我猜测了一下gcd的个数不会很多,然后我就用dfs回溯的时候用map暴力合并就好啦. 终判被卡了MLE..... 需要每次清空一下子树的map... #inc ...
- CF1101D GCD Counting
题目地址:CF1101D GCD Counting zz的我比赛时以为是树剖或者点分治然后果断放弃了 这道题不能顺着做,而应该从答案入手反着想 由于一个数的质因子实在太少了,因此首先找到每个点的点权的 ...
- Codeforces 954H Path Counting 【DP计数】*
Codeforces 954H Path Counting LINK 题目大意:给你一棵n层的树,第i层的每个节点有a[i]个儿子节点,然后问你树上的简单路径中长度在1~n*2-2之间的每个有多少条 ...
- CF EDU 1101D GCD Counting 树形DP + 质因子分解
CF EDU 1101D GCD Counting 题意 有一颗树,每个节点有一个值,问树上最长链的长度,要求链上的每个节点的GCD值大于1. 思路 由于每个数的质因子很少,题目的数据200000&l ...
- GCD Counting Codeforces - 990G
https://www.luogu.org/problemnew/show/CF990G 耶,又一道好题被我浪费掉了,不会做.. 显然可以反演,在这之前只需对于每个i,统计出有多少(x,y),满足x到 ...
- CodeForces - 1101D:GCD Counting (树分治)
You are given a tree consisting of n vertices. A number is written on each vertex; the number on ver ...
- codeforces 582A. GCD Table 解题报告
题目链接:http://codeforces.com/problemset/problem/582/A 网上很多题解,就不说了,直接贴代码= = 官方题解: http://codeforces.com ...
- D. GCD Counting(树上dp)
题目链接:http://codeforces.com/contest/1101/problem/D 题目大意:给你n个点,每个点都有权值,然后给你边的关系,问你树上的最大距离.(这里的最大距离指的是这 ...
随机推荐
- 【CF Round 434 A. k-rounding】
Time limit per test1 second memory limit per test 256 megabytes input standard input output standard ...
- [学习笔记]对未来做出承诺的DP小结
这是一种DP状态设计方法. 有些题,当你必须以一个顺序往后填的话,然而后面的填法会对之前产生影响,那么,不妨在之前就对未来怎么填做出承诺. 通俗的讲,就是对未来打一个表. 然后后面填的时候,直接查表转 ...
- php spl库的使用(PHP标准库)【摘抄引用】
文章来源与推荐阅读:阮一峰--PHP SPL笔记 && PHP SPL使用方法和他的威力 1.SPL 是什么? SPL:standard php library php标准库,此 ...
- GET和POST本质上有什么区别,这才是标准答案
不知道各位读者在面试的时候,有没有被问过这个问题:"请说一下GET和POST两者的本质区别".基本上做过WEB开发的,对这个问题,都可以回答出一堆的区别. 比如: 最直接的区别,G ...
- Exceptioninthread"main"java.lang.ClassNotFoundsException的问题
报错如下: Exceptioninthread"main"java.lang.ClassNotFoundsException 大致可以判断出是无法定位到main方法,应该是用mav ...
- sql 批量更新表中多字段为不同的值
,),,),rand()) select newid() ,) update tablename , FB,)) , ), FC,)) , )
- 平衡树之splay讲解
首先来说是splay是二叉搜索树,它可以说是线段树和SBT的综合,更可以解决一些二者解决不了的问题,splay几乎所有的操作都是由splay这一操作完成的,在介绍这一操作前我们先介绍几个概念和定义 二 ...
- centos python2.6升级到2.7出现的问题
centos自带的python版本为2.6,在使用tornado时会出现如下报错: NameError: global name 'memoryview' is not defined 因此需要升级到 ...
- unicode字符串解码显示
# encoding: utf-8 ''' unicode字符串解码显示 ''' import sys reload(sys) sys.setdefaultencoding('utf-8') a = ...
- Linux设备模型(3)_Uevent【转】
转自:http://www.wowotech.net/device_model/uevent.html 1. Uevent的功能 Uevent是Kobject的一部分,用于在Kobject状态发生改变 ...