BZOJ 5293
-
题目
-
分析
考虑 l c a lca lca 。。
注意到 k k k 的范围只有 50 50 50 这提示我们再询问之前预处理所有的 k k k 下的前缀和,在询问中统计即可。注意取模。
-
代码
const int SIZE = 300010; const int mod = 998244353; ll f[SIZE][20], d[SIZE], dist[SIZE]; int ver[2 * SIZE], Next[2 * SIZE], edge[2 * SIZE], head[SIZE]; int T, n, m, tot, t; queue<int> q; ll sum[SIZE][55]; inline ll ksm(ll a, ll b) { ll ans = 1 % mod; while (b > 0) { if (b & 1) ans = ans * a % mod; b >>= 1; a = a * a % mod; } return ans % mod; } inline void add(int x, int y, int z) { ver[++tot] = y; edge[tot] = z; Next[tot] = head[x]; head[x] = tot; } inline void bfs() { q.push(1); d[1] = 1; while (q.size()) { int x = q.front(); q.pop(); for (int i = head[x]; i; i = Next[i]) { int y = ver[i]; if (d[y]) continue; d[y] = d[x] + 1; dist[y] = dist[x] + edge[i]; f[y][0] = x; for (int j = 1; j <= t; j++) f[y][j] = f[f[y][j - 1]][j - 1]; q.push(y); } } } inline int lca(int x, int y) { if (d[x] > d[y]) swap(x, y); for (int i = t; i >= 0; i--) if (d[f[y][i]] >= d[x]) y = f[y][i]; if (x == y) return x; for (int i = t; i >= 0; i--) if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i]; return f[x][0]; } int main() { read(n); t = (int)(log(n) / log(2)) + 1; for (register int i = 1; i <= n; i++) head[i] = d[i] = 0; tot = 0; for (register int i = 1; i < n; i++) { int x, y; read(x); read(y); add(x, y, 1), add(y, x, 1); } bfs(); read(m); int p = 0; ll maxn = 0; for (int i = 1; i <= n; i++) { if (d[i] > maxn) { maxn = d[i]; p = i; } } for (int k = 1; k <= 50; k++) { for (ll i = 1; i <= d[p]; i++) { sum[i][k] = sum[i - 1][k] + ksm(i - 1, k); } } ll ans = 0; for (register int i = 1; i <= m; i++) { int x, y, k; read(x); read(y); read(k); ans = 0; int _ = lca(x, y); ans = ans + (sum[d[x]][k] - sum[d[_] - 1][k]) % mod; ans %= mod; ans = ans + (sum[d[y]][k] - sum[d[_]][k]) % mod; ans %= mod; printf("%lld\n", ans); } return 0; }
-
题型
L C A LCA LCA + 树上前缀和