【题目链接】
https://www.lydsy.com/JudgeOnline/problem.php?id=5293
【题解】
大力
O(N∗K)
O
(
N
∗
K
)
预处理,然后每次询问时倍增求LCA。
这能算省选题?
【代码】
# include <bits/stdc++.h>
# define ll long long
# define inf 0x3f3f3f3f
# define N 300100
# define T 20
# define K 50
using namespace std;
int read(){
int tmp = 0, fh = 1; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') fh = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9'){tmp = tmp * 10 + ch - '0'; ch = getchar(); }
return tmp * fh;
}
struct Node{
int data, next;
}e[N * 2];
const int P = 998244353;
int head[N], place, dad[N][T + 1], f[N][K + 1], n, dep[N], m;
void build(int u, int v){
e[++place].data = v; e[place].next = head[u]; head[u] = place;
}
void dfs(int x, int fa){
dep[x] = dep[fa] + 1; dad[x][0] = fa;
for (int ed = head[x]; ed != 0; ed = e[ed].next)
if (e[ed].data != fa)
dfs(e[ed].data, x);
}
void pre(){
for (int i = 1, j = 1; j * 2 <= n; i++, j *= 2)
for (int k = 1; k <= n; k++)
dad[k][i] = dad[dad[k][i - 1]][i - 1];
}
int lca(int u, int v){
if (dep[u] > dep[v]) swap(u, v);
for (int i = T; i >= 0; i--)
if (dep[dad[v][i]] >= dep[u])
v = dad[v][i];
if (u == v) return u;
for (int i = T; i >= 0; i--)
if (dad[u][i] != dad[v][i])
u = dad[u][i], v = dad[v][i];
return dad[u][0];
}
int main(){
// freopen("C.in", "r", stdin);
// freopen(".out", "w", stdout);
n = read();
for (int i = 1; i < n; i++){
int u = read(), v = read();
build(u, v); build(v, u);
}
dep[0] = -1;
dfs(1, 0);
pre();
for (int i = 0; i <= n; i++){
f[i][0] = 1;
for (int j = 1; j <= K; j++)
f[i][j] = 1ll * f[i][j - 1] * i % P;
if (i != 0){
for (int j = 1; j <= K; j++)
f[i][j] = (f[i][j] + f[i - 1][j]) % P;
}
}
m = read();
for (int i = 1; i <= m; i++){
int u = read(), v = read(), k = read();
int l = lca(u, v);
ll num = 1ll * f[dep[u]][k] + f[dep[v]][k] - f[dep[l]][k];
if (l != 1) num = num - f[dep[dad[l][0]]][k];
num = (num % P + P) % P;
printf("%lld\n", num);
}
return 0;
}