0分帮忙调试一下- -
查看原帖
0分帮忙调试一下- -
219651
apcesk楼主2024/8/16 19:40
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 3e5 + 10, MOD = 998244353;
vector <int> E[N];// 存树 
int n, k;// n个点,k次询问 
int dep[N] = {}; // 节点的深度 
//	sum[N], // 深度前缀和 
//int lg[N];
int st[N][23];
int data[N][55];// data[i][j]从根节点到点i
int fastmi(int, int);
/**
	给出一棵有根树:询问一条路径上所有节点深度的次方和。
	1号节点为数根。
	求点的深度和,那么树上前缀和即为点的深度和
	根节点的深度为1
	那么节点k的深度为sum[k]的话
	则a到b的路径深度之和=
	sum[a] + sum[b] - 2*sum[lca(a,b)] 
	----
	需要快速求出两点的lca -> 倍增搞定  
	预处理出前缀和,深搜搞定
	还需要快速幂
*/
void dfs(int now, int father) {// 当前点和其父节点
	dep[now] = dep[father] + 1;// 更新当前节点的深度
	st[now][0] = father;// 向上跳2^0是其父亲 
	for (int i = 1;i <= 50;i++) {// 预处理出这条路径的和 
		data[now][i] = (data[father][i] + fastmi(dep[now], i) + MOD) % MOD;
//		printf("data[%lld][%lld]: %lld\n", now, i, data[now][i]);
	}
//	printf("---\n");
	for (int to : E[now]) {
		if (to == father) continue;// 跳过父节点,防止回头
		dfs(to, now);// 继续递归其子节点
	}
}
int lca(int a, int b) {// 求点a和点b的最近公共祖先
	if (dep[a] < dep[b]) swap(a, b);
//	printf("1111\n");
	for (int j = 20;j >= 0;j--) {
		if (dep[st[a][j]] >= b) {
			a = st[a][j];
		}
	}
	if (a == b) return b;
	// 开始一起跳
	for (int j = 20;j >= 0;j--) {
		if (st[a][j] != st[b][j]) {
			a = st[a][j], b = st[b][j];
		}
	}
	return st[a][0];
}
int fastmi(int a, int b) {// 快速幂 
	int res = 1;
	while (b) {
		if (b & 1) res = res * a % MOD;
		a = a * a % MOD;
		b >>= 1;
	}
	return res % MOD;
}
signed main() {
	// step 1、读题、声明变量
	// step 2、输入
	scanf("%lld", &n);
	for (int i = 1;i < n;i++) {
		int f, t;
		scanf("%lld%lld", &f, &t);
		E[f].push_back(t);// 建树 
	}
//	for (int i = 2;i <= n;i++) lg[i] = lg[i >> 1] + 1;// 对数表
	// step 3、处理
	dep[1] = -1;
	dfs(1, 1);// 处理树和ST表
	for (int j = 1;j <= 21;j++) {
		for (int i = 1;i <= n;i++) {
			st[i][j] = st[st[i][j - 1]][j - 1];
		}
	}
	scanf("%lld", &k);
	int a, b, c;// 点a到点b的路径的c次方和 
	while (k--) {
		scanf("%lld%lld%lld", &a, &b, &c);
		// step 4、输出
		int ff = lca(a, b);
		int sum1 = (data[a][c] + data[b][c] + MOD) % MOD;
		int sum2 = (data[ff][c] + data[st[ff][0]][c] + MOD) % MOD;
		printf("%lld\n", ((sum1 - sum2) + MOD) % MOD);
	}
	return 0;
}
/**
5
1 2
1 3
2 4
2 5
2
1 4 5
5 4 45
*/

2024/8/16 19:40
加载中...