CodeForces - 986E Prince's Problem

Description

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

\(n,m\le 10^5,1\le a_i\le 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\n", ans[i]);
	return 0;
}

posted @ 2018-10-08 08:45  aziint  阅读(229)  评论(0编辑  收藏  举报
Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.