CodeForces990G:GCD Counting(树分治+GCD)
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
题意:求所有简单路径的GCD,统计数量。
思路:不难想到是分治,问题转化为多个小问题:统计经过某点的路径的GCD,由于GCD具有收敛性,不同GCD的数量级是log级别的,虽然有多个链,但感觉gcd是数量就算不会太多,2333,我猜复杂度不超过O(N*logN*logN*logN)级别吧。所以对于当前子树,每次访问一条链的时候统计这条链和之前所有GCD的gcd。。。。说不清楚,反正一想就会相通的东西。
(具有收敛性的有:GCD,或,且...)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=;
const int inf=0x7FFFFFFF;
int Laxt[maxn],Next[maxn<<],To[maxn<<],cnt,N,sn;
int a[maxn],sz[maxn],son[maxn],vis[maxn],root; ll ans[maxn];
map<int,int>mp,tp;
map<int,int>::iterator it1,it2;
inline void read(int &x) {
x=; char c=getchar();
while(c>''||c<'') c=getchar();
while(c<=''&&c>='') x=(x<<)+(x<<)+c-'',c=getchar();
}
void add(int u,int v){
Next[++cnt]=Laxt[u];
Laxt[u]=cnt; To[cnt]=v;
}
void getroot(int u,int fa) //找重心
{
sz[u]=; son[u]=;
for(int i=Laxt[u];i;i=Next[i]){
if(To[i]!=fa&&!vis[To[i]]){
getroot(To[i],u);
sz[u]+=sz[To[i]];
son[u]=max(son[u],sz[To[i]]);
}
}
son[u]=max(son[u],sn-son[u]);
if(root==||son[root]>son[u]) root=u;
}
void getans(int u,int fa,int num) //对于当前链产生的新GCD
{
tp[num]++;
for(int i=Laxt[u];i;i=Next[i]){
if(!vis[To[i]]&&To[i]!=fa){
getans(To[i],u,__gcd(num,a[To[i]]));
}
}
}
void solve(int u) //解决以u为根的子问题
{
mp.clear(); mp[a[u]]++; ans[a[u]]++;
for(int i=Laxt[u];i;i=Next[i])
if(!vis[To[i]]) {
tp.clear(); getans(To[i],u,__gcd(a[u],a[To[i]]));
for(it1=mp.begin();it1!=mp.end();it1++)
for(it2=tp.begin();it2!=tp.end();it2++){
int g=__gcd((*it1).first,(*it2).first);
ans[g]+=(ll)(*it1).second*(*it2).second;
}
for(it2=tp.begin();it2!=tp.end();it2++)
mp[(*it2).first]+=(*it2).second;
}
}
void dfs(int u) //分治
{
vis[u]=; solve(u);
for(int i=Laxt[u];i;i=Next[i]){
if(vis[To[i]]) continue;
root=; sn=sz[To[i]];
getroot(To[i],); dfs(root);
}
}
int main()
{
read(N); int u,v,Max=;
for(int i=;i<=N;i++) read(a[i]),Max=max(Max,a[i]);
for(int i=;i<N;i++) {
read(u);read(v);
add(u,v); add(v,u);
}
root=; sn=N; getroot(,); dfs(root);
for(int i=;i<=Max;i++) if(ans[i]) printf("%d %I64d\n",i,ans[i]);
return ;
}
CodeForces990G:GCD Counting(树分治+GCD)的更多相关文章
- CF1101D GCD Counting 点分治+质因数分解
题意:求最长的树上路径点值的 $gcd$ 不为 $1$ 的长度. 由于只要求 $gcd$ 不为一,所以只要 $gcd$ 是一个大于等于 $2$ 的质数的倍数就可以了. 而我们发现 $2\times 1 ...
- CF990G GCD Counting 点分治+容斥+暴力
只想出来 $O(nlogn\times 160)$ 的复杂度,没想到还能过~ Code: #include <cstdio> #include <vector> #includ ...
- CF1101D GCD Counting
题目地址:CF1101D GCD Counting zz的我比赛时以为是树剖或者点分治然后果断放弃了 这道题不能顺着做,而应该从答案入手反着想 由于一个数的质因子实在太少了,因此首先找到每个点的点权的 ...
- CF EDU 1101D GCD Counting 树形DP + 质因子分解
CF EDU 1101D GCD Counting 题意 有一颗树,每个节点有一个值,问树上最长链的长度,要求链上的每个节点的GCD值大于1. 思路 由于每个数的质因子很少,题目的数据200000&l ...
- hdu 5869 区间不同GCD个数(树状数组)
Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K ( ...
- Ultimate Weirdness of an Array CodeForces - 671C (gcd,线段树)
大意: 定义一个数列的特征值为两个数gcd的最大值, $f(l,r)$表示数列删除区间$[l,r]$的元素后剩余元素的特征值, 求$\sum_{i=1}^n\sum_{j=i}^n{f(i,j)}$ ...
- Educational Codeforces Round 45 (Rated for Div. 2) G - GCD Counting
G - GCD Counting 思路:我猜测了一下gcd的个数不会很多,然后我就用dfs回溯的时候用map暴力合并就好啦. 终判被卡了MLE..... 需要每次清空一下子树的map... #inc ...
- HDU 5869.Different GCD Subarray Query-区间gcd+树状数组 (神奇的标记右移操作) (2016年ICPC大连网络赛)
树状数组... Different GCD Subarray Query Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/6 ...
- D - 小Z的加油店 线段树+差分+GCD
D - 小Z的加油店 HYSBZ - 5028 这个题目是一个线段树+差分+GCD 推荐一个差分的博客:https://www.cnblogs.com/cjoierljl/p/8728110.ht ...
随机推荐
- SilverLight-DataBinding:二、Bingding to a Collection Objects(绑定一个集合对象)
ylbtech-SilverLight-DataBinding: Bingding to a Collection Objects(绑定一个集合对象) 1.A, Building a Data Ob ...
- 如何使用电骡eMule上传资源
1 在电脑中创建一个文件夹专门为上传资源使用 在里面放入任意文件并右击显示ED2K链接 链接效果如下 2 登陆verycd网站,并点击上传资源 复制ED2K地址并选择分类
- HAProxy简单使用
一.HAProxy简介及定位 HAProxy 是一款基于TCP和HTTP应用的具备高可用行且负载均衡的代理软件.HAProxy是完全免费的,借助HAProxy可以快速.可靠地提供基于T ...
- (利用DOM)在新打开的页面点击关闭当前浏览器窗口
1.在开发过程中我们前端的用户体验中有时候会要求点击一个按钮,关闭当前浏览器窗口,用HTML DOM就可做到 2.注意:本次写法要求在新窗口中关闭.target="_blank" ...
- 不能hadoop-daemon.sh start datanode, 显示 错误: 找不到或无法加载主类 ”-Djava.library.path=.home.hadoop.apps.hadoop-2.6.4.lib”
这两行代码是用来解决一个Hadoop,32位和64位不兼容的警告的,(这个警告可以忽略) 这两行加到mini2~min4后, export HADOOP_COMMON_LIB_NATIVE_DIR=$ ...
- 福昕熊雨前:PDFium开源项目的背后
今天编译android的时候,无意中看到命令行提示出输出编译external/pdfium这个目录,于是乎上百度搜索了一下,找到了如下关于PDF文件解析的开源代码的文章: http://www.csd ...
- memcache及其telnet命令使用详解
1.启动Memcache 常用参数memcached 1.4.3-p <num> 设置端口号(默认不设置为: 11211)-U <num> UDP监听端口 ...
- disabled和readonly
项目中,有一个input控件,input的值需要通过点击一个javascript链接,从弹出的对话框中所列出的项中选择.而不能从input框中直接输入. 刚开始将input的disabled属性设置为 ...
- public,protected,private,static,final的区别(转载)
1.类 (1)在java中有public.protected.private三种显示的修饰符用于控制可见性,package不是显示的修饰符,它是隐含的,即如果在类.变量等前没加显示的可见性修饰符,那它 ...
- Bubble Cup X - Finals [Online Mirror] B. Neural Network country 矩阵快速幂加速转移
B. Neural Network country time limit per test 2 seconds memory limit per test 256 megabytes Due to t ...