[换根dp] CF771C

posted on 2024-01-27 12:53:50 | under 题集 | source

一个稍有不同的解法?

题意

给出一棵有 \(n\) 个点的树,定义 \(dis(i,j)\) 为树上两点距离,求 \(\sum\limits_{1\le i < j \le n} \lceil \frac {dis(i,j)}{k} \rceil\)

\(n\le200000,1\le k\le5\)

思路

容易想到换根 \(\rm dp\) 求出每个点到其它点的距离之和 \(S_i\),然后除以 \(k\),但是由于有向上取整所以不好处理。

如何解决呢?发现不好对每个点单独讨论,也就是说最终式子最好含有 \(S_i\) 项。

我们知道 \(\lceil \frac ak \rceil = \frac {a+k-a \bmod k}{k}\),只要把 \(a\) 除不尽的部分补上即可(当然前提是 \(k\nmid a\) )。

根据上式,有:\(\sum \lceil \frac {a_i}{k} \rceil = \sum \frac {a_i+k-a_i \bmod k}{k}=\frac {\sum a_i + \sum (k-a_i\bmod k)} {k}\)

诶,这样就出现 \(S_i\) 项了啊。把刚刚推出的式子带到这题里,节点 \(i\) 对答案的贡献就是:\(\frac {S_i+\sum k-dis(i,j) \bmod k}k\)

考虑怎么求 \(\sum k-dis(i,j) \bmod k\) 这一项即可。注意到 \(k\) 很小,容易想到枚举余数 \(c\),统计 \(dep(i,j) \bmod k = c\) 的数量即可。

具体的,记 \(g_{i,c}/f_{i,c}\) 为子树内/子树外有多少个点 \(j\) 满足 \(dep(i,j)\bmod k=c\),直接维护即可。

复杂度 \(O(nk)\),可以通过。最后注意:上述过程统计的是有序数对,转成无序数对要除以 \(2\)

代码

#include<bits/stdc++.h>
using namespace std;

#define int long long
const int N = 2e5 + 5, K = 5;
int n, k, g[N], f[N], son[N], u, v;
int G[N][K], F[N][K], Gs[N][K], ans;
vector<int> to[N];

inline void dfs1(int u, int fa){
	son[u] = 1;
	for(auto v : to[u])
		if(v ^ fa){
			dfs1(v, u);
			son[u] += son[v];
			g[u] += g[v] + son[v];
			
			for(int c = 0; c < k; ++c)
				G[u][(c + 1) % k] += G[v][c], Gs[u][c] += G[v][c];
			++G[u][1 % k], ++Gs[u][0];
		}
}
inline void dfs2(int u, int fa){
	if(fa){
		f[u] = f[fa] + n - son[fa] + 1;
		f[u] += g[fa] - g[u] - son[u] + son[fa] - son[u] - 1;
		
		for(int c = 0; c < k; ++c){
			F[u][(c + 1) % k] += F[fa][c];
			F[u][(c + 2) % k] += Gs[fa][c] - G[u][c] - (c == 0);
		}
		++F[u][1 % k];
	}
	for(auto v : to[u])
		if(v ^ fa) dfs2(v, u);
}
signed main(){
	cin >> n >> k;
	for(int i = 1; i < n; ++i)
		scanf("%lld%lld", &u, &v), to[u].push_back(v), to[v].push_back(u);
	dfs1(1, 0), dfs2(1, 0);
	for(int i = 1; i <= n; ++i){
		int res = g[i] + f[i];
		for(int c = 1; c < k; ++c)
			res += (k - c) * (G[i][c] + F[i][c]);
		ans += res / k;
	}
	cout << ans / 2;
	return 0;
}
posted @ 2026-01-12 20:14  Zwi  阅读(1)  评论(0)    收藏  举报