传送门

思路:

直接上点分治+容斥计算每个因数对应的贡献即可。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
typedef long long ll;
const int N=1e5+5;
vector<int>e[N],fac[N],coe[N];
int n,a[N],lim=0,all,mx,siz[N],rt,Tim[N],cnt[N],mul[N],tim=0;
bool vis[N],chk[N];
ll ans=0;
inline int get(int x){
	if(mul[x])return mul[x];
	if(x<2)return mul[x]=x;
	int ret=1;
	for(ri i=0;i<fac[x].size();++i)ret*=fac[x][i];
	return mul[x]=ret;
}
inline void get_coef(int pos,int mul,int a){
	if(pos==fac[a].size()){if(~mul)coe[a].push_back(mul);return;}
	get_coef(pos+1,mul,a);
	get_coef(pos+1,-fac[a][pos]*mul,a);
}
inline void init(){
	for(ri i=2;i<=lim;++i)if(!vis[i])for(ri j=i;j<=lim;j+=i)vis[j]=1,fac[j].push_back(i);
	for(ri i=1,x;i<=n;++i)vis[i]=0,a[i]=get(a[i]);
}
void getroot(int p,int fa){
	siz[p]=1;
	int ms=0;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa||vis[v])continue;
		getroot(v,p),siz[p]+=siz[v],ms=max(ms,siz[v]);
	}
	ms=max(ms,all-siz[p]);
	if(ms<=mx)rt=p,mx=ms;
}
inline int query(int x){return Tim[x]==tim?cnt[x]:0;}
inline int ask(int x){
	int ret=0;
	if(!chk[x])get_coef(0,-1,x),chk[x]=1;
	for(ri i=0;i<coe[x].size();++i)ret+=coe[x][i]/abs(coe[x][i])*query(abs(coe[x][i]));
	return ret;
}
inline void update(int x){Tim[x]==tim?++cnt[x]:cnt[x]=1,Tim[x]=tim;}
inline void change(int x){
	if(!chk[x])get_coef(0,-1,x),chk[x]=1;
	for(ri i=0;i<coe[x].size();++i)update(abs(coe[x][i]));
}
inline int gcd(int a,int b){int t;while(b){t=a,a=b,b=t-t/a*a;}return a;}
void dfs(int p,int fa,int g,int coef){
	g=gcd(g,a[p]),ans+=coef*ask(g),change(g),siz[p]=1;
	for(ri i=0,v;i<e[p].size();++i){
		if(vis[v=e[p][i]]||v==fa)continue;
		dfs(v,p,g,coef),siz[p]+=siz[v];
	}
}
inline void solve(int p){
	vis[p]=1;
	++tim;
	change(a[p]);
	for(ri i=0,v;i<e[p].size();++i)if(!vis[v=e[p][i]])dfs(v,p,a[p],1);
	for(ri i=0,v;i<e[p].size();++i){
		if(vis[v=e[p][i]])continue;
		++tim,dfs(v,p,a[p],-1),mx=all=siz[v],getroot(v,p),solve(rt);
	}
}
int main(){
	n=read();
	for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
	for(ri i=1;i<=n;++i)a[i]=read(),lim=max(lim,a[i]);
	init();
	rt=0,mx=all=n,getroot(1,0),solve(rt);
	cout<<(ll)n*(n-1)/2-ans;
	return 0;
}

2019.03.29 NOIP训练 友好国度(点分治+容斥)的更多相关文章

  1. 2019.03.25 NOIP训练 匹配(match)(贪心)

    题意简述: 思路: 直接考虑把人和物品都看成二维平面上面的a,ba,ba,b两类点,然后一个aaa和bbb匹配的条件是xa≤xb&&ya≤ybx_a\le x_b\&\& ...

  2. 2019.7.29 NOIP模拟测试10 反思总结【T2补全】

    这次意外考得不错…但是并没有太多厉害的地方,因为我只是打满了暴力[还没去推T3] 第一题折腾了一个小时,看了看时间先去写第二题了.第二题尝试了半天还是只写了三十分的暴力,然后看到第三题是期望,本能排斥 ...

  3. 2019.03.29 bzoj5463: [APIO2018] 铁人两项(圆方树+树形dp)

    传送门 题意简述:给你一张无向图,问你满足存在从a−>b−>ca->b->ca−>b−>c且不经过重复节点的路径的有序点对(a,b,c)(a,b,c)(a,b,c) ...

  4. 2019.03.29 bzoj3323: [Scoi2013]多项式的运算(非旋treap)

    传送门 题意:定义一个无穷项的多项式f(x)f(x)f(x),初始各项系数都为0,现在有几种操作 将xLx^LxL到xRx^RxR这些项的系数乘上某个定值v 将xLx^LxL到xRx^RxR这些项的系 ...

  5. 2019.01.24 NOIP训练 旅行(轮廓线dp)

    传送门 题意简述: 给一个n∗mn*mn∗m的有障碍的网格图,问你从左上角走到左下角并覆盖所有可行格子的路径条数. 思路: 路径不是很好算. 将图改造一下,在最前面添两列,第一列全部能通过,第二列只有 ...

  6. 2019.01.21 NOIP训练 可持久化序列【模板】(可持久化treap)

    传送门 题意简述:支持在把某个数插入到某版本的第k个位置,删除某版本第k个数,询问第k个数. 思路:用可持久化treaptreaptreap维护区间第kkk个位置的数是啥就可以了. 代码

  7. 2019.01.21 NOIP训练 ak树(点分治)

    传送门 题意简述:给一棵带权树,问在上面随机选两个点距离是4的倍数的概率. 思路: 由于总方案数为定值n2n^2n2,所以只用求总方案数. 这个跟聪聪可可差不多,可以用类似树形dpdpdp的方法边点分 ...

  8. 2019.01.02 NOIP训练 三七二十一(生成函数)

    传送门 生成函数基础题. 题意简述:求由1,3,5,7,9这5个数字组成的n位数个数,要求其中3和7出现的次数都要是偶数. 考虑对于每个数字构造生成函数. 对于1,5,9:∑nxnn!=ex\sum_ ...

  9. 2018.10.29 NOIP训练 数据结构(带修改莫队)

    传送门 带修莫队板题. 直接按照经典写法做就行了. 代码

随机推荐

  1. 拾遗----javascript一些实用方法

    1. join() join() 方法用于把数组中的所有元素放入一个字符串.元素是通过指定的分隔符进行分隔的. var ids = [];                 for(var i = 0 ...

  2. CountDownLatch原理及使用场景

    CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量.每当一个线程完成了自己的任务后,计数器的值就会减1.当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁 上 ...

  3. Linux命令:popd

    语法 popd [-n] [+N | -N | dir] 把目录弹栈,就是从栈里删除.popd只有删除一种意思,不像pushd,既有压栈,又有移动栈内目录的功能. 不带任何参数,模式删除栈顶,即最上面 ...

  4. Centos 7 安装composer和Laravel

    composer安装 我安装了lnmp到Centos7里,所以可以直接运行curl -sS https://getcomposer.org/installer | php把安装的composer.ph ...

  5. 关于js-angularJS的路由传参

    使用angular进行网页跳转传参 app.controller('payController', function ($scope, $location, payService) { 注明$loca ...

  6. Longest Palindrome 最长回文串问题

    1.题目 Given a string s, find the longest palindromic substring in s. You may assume that the maximum ...

  7. 解决ajax请求默认不支持重定向问题

    1,Ajax默认是不支持重定向的,只局部刷新数据,不跳转页面. 2,后台代码处理: @RequestMapping("/updateCurrentUser") public Str ...

  8. Linux源码安装JDK1.8

    Linux源码安装Java 1.到官网下载 jdk-8u131-linux-x64.tar.gz 官网地址:http://www.oracle.com/technetwork/java/javase/ ...

  9. pandas的简单使用

    pandas可以对数据进行整理分析 因为要对excel中的源数据进行分组和处理,所以想到用pandas来处理.试用过确实比自己去读写快捷很多 (实际pandas底层也是用xlrd,xlwt两个第三方包 ...

  10. linux应用之test命令详细解析

    test命令用法. 功能:检查文件和比较值 1)判断表达式 if test  (表达式为真) if test !表达式为假 test 表达式1 –a 表达式2                  两个表 ...