题意:给一棵带点权$w_i$的树,多次询问$(u,v,x)$,求出$\prod\limits_{i\in\text{path}(u,v)}(w_i,x)$

因为是乘法,所以可以把路径询问拆成到根询问,这样就可以离线做了

因为求$\gcd$的本质是质因数指数取$\min$,所以在离线dfs时每到一个点就把它的点权质因数分解打上标记然后统计答案即可

具体地,对于$w_x=\prod\limits_{i=1}^kp_i^{a_i}$,我们把每个$p_i$的$1\cdots a_i$次幂乘上$p_i$的标记,统计答案时对$x=\prod\limits_{i=1}^kp_i^{a_i}$,对每个$p_i$都往答案乘上$[1,a_i]$的标记即可,dfs退栈时除回去以撤销

#include<stdio.h>
#include<vector>
using namespace std;
typedef long long ll;
const int mod=1000000007,T=10000000;
int mul(int a,int b){return a*(ll)b%mod;}
int pr[10000010],d[10000010],s[10000010];
int pow(int a,int b){
	int s=1;
	while(b){
		if(b&1)s=mul(s,a);
		a=mul(a,a);
		b>>=1;
	}
	return s;
}
void sieve(){
	int i,j,M;
	M=0;
	d[1]=1;
	s[1]=1;
	for(i=2;i<=T;i++){
		s[i]=1;
		if(d[i]==0){
			M++;
			pr[M]=d[i]=i;
		}
		for(j=1;j<=M;j++){
			if(pr[j]*(ll)i>T)break;
			d[i*pr[j]]=pr[j];
			if(i%pr[j]==0)break;
		}
	}
}
int h[100010],nex[200010],to[200010],dep[100010],fa[100010][17],M;
void add(int a,int b){
	M++;
	to[M]=b;
	nex[M]=h[a];
	h[a]=M;
}
void dfs(int x){
	dep[x]=dep[fa[x][0]]+1;
	for(int i=h[x];i;i=nex[i]){
		if(to[i]!=fa[x][0]){
			fa[to[i]][0]=x;
			dfs(to[i]);
		}
	}
}
int lca(int x,int y){
	int i;
	if(dep[x]<dep[y])swap(x,y);
	for(i=16;i>=0;i--){
		if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
	}
	if(x==y)return x;
	for(i=16;i>=0;i--){
		if(fa[x][i]!=fa[y][i]){
			x=fa[x][i];
			y=fa[y][i];
		}
	}
	return fa[x][0];
}
struct par{
	int x,f;
	par(int a=0,int b=0){x=a;f=b;}
};
vector<par>v[100010];
int a[100010],val[100010],ans[100010];
void solve(int x){
	int i,j,t;
	for(i=a[x];i>1;){
		for(j=t=d[i];i%t==0;i/=t,j*=t)s[j]=mul(s[j],t);
	}
	for(par p:v[x]){
		for(i=val[p.x];i>1;){
			for(j=t=d[i];i%t==0;i/=t,j*=t)ans[p.x]=mul(ans[p.x],p.f?s[j]:pow(s[j],mod-2));
		}
	}
	for(i=h[x];i;i=nex[i]){
		if(to[i]!=fa[x][0])solve(to[i]);
	}
	for(i=a[x];i>1;){
		for(j=t=d[i];i%t==0;i/=t,j*=t)s[j]=mul(s[j],pow(t,mod-2));
	}
}
int main(){
	sieve();
	int n,q,i,j,x,y;
	scanf("%d",&n);
	for(i=1;i<n;i++){
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	for(i=1;i<=n;i++)scanf("%d",a+i);
	dfs(1);
	for(j=1;j<17;j++){
		for(i=1;i<=n;i++)fa[i][j]=fa[fa[i][j-1]][j-1];
	}
	scanf("%d",&q);
	for(i=1;i<=q;i++){
		scanf("%d%d%d",&x,&y,val+i);
		j=lca(x,y);
		v[x].push_back(par(i,1));
		v[y].push_back(par(i,1));
		v[j].push_back(par(i,0));
		v[fa[j][0]].push_back(par(i,0));
		ans[i]=1;
	}
	solve(1);
	for(i=1;i<=q;i++)printf("%d\n",ans[i]);
}

[CF986E]Prince's Problem的更多相关文章

  1. 【题解】CF986E Prince's Problem(树上差分+数论性质)

    [题解]CF986E Prince's Problem(树上差分+数论性质) 题目大意: 给定你一棵树,有点权\(val_i\le 10^7\).现在有\(m\)组询问给定参数\(x,y,w\)问你对 ...

  2. [Codeforces 986E] Prince's Problem

    [题目链接] https://codeforces.com/contest/986/problem/E [算法] X到Y的路径积 , 可以转化为X到根的路径积乘Y到根的路径积 , 除以LCA到根的路径 ...

  3. Codeforces986E Prince's Problem 【虚树】【可持久化线段树】【树状数组】

    我很喜欢这道题. 题目大意: 给出一棵带点权树.对每个询问$ u,v,x $,求$\prod_{i \in P(u,v)}gcd(ai,x)$.其中$ P(u,v) $表示$ u $到$ v $的路径 ...

  4. Codeforces 986E - Prince's Problem(树上前缀和)

    题面传送门 题意: 有一棵 \(n\) 个节点的树,点上有点权 \(a_i\),\(q\) 组询问,每次询问给出 \(u,v,w\),要求: \(\prod\limits_{x\in P(u,v)}\ ...

  5. 超强语感训练文章(Provided by Rocky teacher Prince)

    Content: Class1 My name is Prince Class2 Welcome to our hotel Class3 We’re not afraid of problems Cl ...

  6. 强连通+二分匹配(hdu4685 Prince and Princess)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

  7. 10635 - Prince and Princess

    Problem D Prince and Princess Input: Standard Input Output: Standard Output Time Limit: 3 Seconds In ...

  8. UVa10653.Prince and Princess

    题目连接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem& ...

  9. Prince and Princess HDU - 4685(匹配 + 强连通)

    Prince and Princess Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Othe ...

随机推荐

  1. API网关Kong部署和使用文档

    KONG安装使用说明 系统版本:ubuntu14 1.下载安装包 $ wget https://github.com/Mashape/kong/releases/download/0.8.3/kong ...

  2. 从零开始学习MXnet(四)计算图和粗细粒度以及自动求导

    这篇其实跟使用MXnet的关系不大,但对于我们理解深度学习的框架设计还是很有帮助的. 首先还是对promgramming models的一个简单介绍,这个东西实际上是在编译里面经常出现的东西,我们在编 ...

  3. LwIP - 打开keepalive功能

    在服务器端打开keepalive功能 1.保证LWIP_TCP_KEEPALIVE被定义为1,(这样TCP_KEEPIDLE.TCP_KEEPINTVL和TCP_KEEPCNT 设置才有效) 2. i ...

  4. spring aop与aspectj

    AOP:面向切面编程 简介 AOP解决的问题:将核心业务代码与外围业务(日志记录.权限校验.异常处理.事务控制)代码分离出来,提高模块化,降低代码耦合度,使职责更单一. AOP应用场景: 日志记录.权 ...

  5. O(n^2)以及O(nlogn)时间复杂度的排序算法

    O(n^2)的算法 都是做的升序. 简单选择排序 思路:每次选择还未排序的区间的最小值和未排序区间的第一个值交换. function selectSort(arr){ for(let i = 0; i ...

  6. MyEclipse快捷键大全(转)1

    Ctrl+1 快速修复(最经典的快捷键,就不用多说了) Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加) Ctrl+Alt+↑ 复制当前行到上一行(复制增加) Alt+ ...

  7. Lucene6去掉了Filter但是可以用BooleanQuery实现Filter查询

    Lucene在6.0版本之后彻底废除了Filter的使用,采用BooleanQuery来实现Filter的功能,核心代码如下: TermQuery termQuery = new TermQuery( ...

  8. Python基础(5)_文件操作

    一.文件处理流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 二.文件打开模式 打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文 ...

  9. [bzoj2124]等差子序列——线段树+字符串哈希

    题目大意 给一个1到N的排列\(A_i\),询问是否存在\(p_i\),\(i>=3\),使得\(A_{p_1}, A_{p_2}, ... ,A_{p_len}\)是一个等差序列. 题解 显然 ...

  10. sublime text 2学习(二):创建可复用的代码片段

    对于前端工程师来讲,写一个html页面的基本结构是体力活,每次去拷贝一个也麻烦,sublime text 2 提供了一个很好的复用代码片段.下面介绍一下创建一个html5的代码片段的过程. 在菜单上点 ...