zoukankan      html  css  js  c++  java
  • CodeForces

    Description

    给一棵树,每个点有点权 (a_i) ,每次给 (u,v,x) ,求 (u)(v) 路径上每个点的点权与 (x)(gcd) 的积。

    (n,mle 10^5,1le a_ile 10^7)

    Solution

    离线,答案相当与四条从根出发的链拼起来,分解质因数。

    #include<bits/stdc++.h>
    using namespace std;
    
    template <class T> void read(T &x) {
    	x = 0; bool flag = 0; char ch = getchar(); for (; ch < '0' || ch > '9'; ch = getchar()) flag |= ch == '-';
    	for (; ch >= '0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - 48; flag ? x = ~x + 1 : 0;
    }
    
    //#pragma GCC diagnostic error "-std=c++14"
    
    #define N 100010
    #define rep(i, a, b) for (auto i = (a); i <= (b); ++i)
    #define drp(i, a, b) for (auto i = (a); i >= (b); --i)
    #define P 1000000007
    
    bool notPri[10000010];
    int pri[664580 + 10], priCnt;
    
    void init(int n) {
    	int m = sqrt(n + 0.5);
    	rep(i, 2, m) if (!notPri[i]) for (int j = i * i; j <= n; j += i) notPri[j] = 1;
    	rep(i, 2, n) if (!notPri[i]) pri[++priCnt] = i;
    }
    
    vector<int> g[N];
    
    int fa[N][18], dep[N];
    void dfs(int u) {
    	rep(i, 1, 17) fa[u][i] = fa[fa[u][i - 1]][i - 1];
    	for (int v : g[u]) if (v ^ fa[u][0]) fa[v][0] = u, dep[v] = dep[u] + 1, dfs(v);
    }
    
    int getLca(int u, int v) {
    	if (dep[u] < dep[v]) swap(u, v);
    	drp(i, 17, 0) if (dep[fa[u][i]] >= dep[v]) u = fa[u][i]; if (u == v) return u;
    	drp(i, 17, 0) if (fa[u][i] ^ fa[v][i]) u = fa[u][i], v = fa[v][i]; return fa[u][0];
    }
    
    struct Data {
    	int x, id;
    	bool type;
    	Data(int x = 0, int id = 0, bool type = 0) : x(x), id(id), type(type) {}
    };
    
    vector<Data> q[N];
    
    int qpow(int x, int k) {
    	int ret = 1;
    	for (; k; k >>= 1, x = 1ll * x * x % P) if (k & 1) ret = 1ll * ret * x % P;
    	return ret;
    }
    
    int a[N], ans[N], cnt[664580 + 10][25];
    
    void update(int val, int del) {
    	for (int i = 1; 1ll * pri[i] * pri[i] <= val; ++i) if (val % pri[i] == 0) {
    		int p = 0;
    		for (; val % pri[i] == 0; val /= pri[i], ++p);
    		cnt[i][p] += del;
    	}
    	if (val != 1) cnt[lower_bound(pri + 1, pri + 1 + priCnt, val) - pri][1] += del;
    }
    
    int query(int val) {
    	int ret = 1;
    	for (int i = 1; 1ll * pri[i] * pri[i] <= val; ++i) if (val % pri[i] == 0) {
    		int p = 0, t = 0;
    		for (; val % pri[i] == 0; val /= pri[i], ++p);
    		rep(j, 1, p) t += cnt[i][j] * j;
    		rep(j, p + 1, 24) t += cnt[i][j] * p;
    		ret = 1ll * ret * qpow(pri[i], t) % P;
    	}
    	if (val == 1) return ret;
    	int pos = lower_bound(pri + 1, pri + 1 + priCnt, val) - pri;
    	int t = 0;
    	rep(i, 1, 24) t += cnt[pos][i];
    	return 1ll * ret * qpow(val, t) % P;
    }
    
    void solve(int u) {
    	update(a[u], 1);
    	for (auto t : q[u]) {
    		if (t.type) ans[t.id] = 1ll * ans[t.id] * query(t.x) % P;
    		else ans[t.id] = 1ll * ans[t.id] * qpow(query(t.x), P - 2) % P;
    	}
    	for (int v : g[u]) if (v != fa[u][0]) solve(v);
    	update(a[u], -1);
    }
    
    #define pb push_back
    
    int main() {
    	init(10000000);
    	int n, m; read(n);
    	rep(i, 2, n) {
    		int u, v; read(u), read(v);
    		g[u].pb(v), g[v].pb(u);
    	}
    	dep[1] = 1; dfs(1);
    	rep(i, 1, n) read(a[i]);
    	read(m);
    	rep(i, 1, m) {
    		int u, v, x; read(u), read(v), read(x);
    		int lca = getLca(u, v);
    		ans[i] = 1;
    		q[u].pb(Data(x, i, 1)), q[v].pb(Data(x, i, 1)), q[lca].pb(Data(x, i, 0));
    		if (lca != 1) q[fa[lca][0]].pb(Data(x, i, 0));
    	}
    	solve(1);
    	rep(i, 1, m) printf("%d
    ", ans[i]);
    	return 0;
    }
    
    
  • 相关阅读:
    webpack基础
    LeetCode232. 用栈实现队列做题笔记
    mysql 时间加减一个月
    leetcode 1381. 设计一个支持增量操作的栈 思路与算法
    LeetCode 141. 环形链表 做题笔记
    leetcode 707. 设计链表 做题笔记
    leetcode 876. 链表的中间结点 做题笔记
    leetcode 143. 重排链表 做题笔记
    leetcode 1365. 有多少小于当前数字的数字 做题笔记
    LeetCode1360. 日期之间隔几天 做题笔记
  • 原文地址:https://www.cnblogs.com/aziint/p/9752455.html
Copyright © 2011-2022 走看看