CF771C Bear and Tree Jumps
阿新 • • 發佈:2020-09-16
直接考慮換根。
但是有個K,不好搞,那就多存點,記錄 \(f_{n,j}\) 為與 \(n\) 距離為 \(j\) 的點的答案(\(f_{n,0}\) 即為自己的答案),那麼可以知道,對於距離不為 \(K\) 的倍數的點,可以直接距離加一,對於距離為 \(K\) 的倍數的點?對於 \(f_{n,0}\) 可以直接從 \(f_{v\in son_n,K-1}\) 轉移,加上 \(siz_{n}-1\) 就好。
所以我們可以列出DP方程
\[\begin{matrix} f_{n,0} = \sum_{v\in son_n}f_{v,K-1} + siz_v \\ f_{n,i} = \sum_{v\in son_n}f_{v,i-1} * [i\ne 0] \end{matrix}\]
#include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef long long ll; const ll MAXN = 1e6+10; struct edge { ll nt, to; } E[MAXN]; ll N, head[MAXN], cnt = -1, ans = 0, K, f[MAXN][7], siz[MAXN]; void add(ll, ll); void dfs(ll, ll); void dfs2(ll, ll); int main() { memset(head, -1, sizeof(head)); scanf("%lld%lld", &N, &K); for (ll i = 1, x, y; i < N; i++) { scanf("%lld%lld", &x, &y); add(x, y); add(y, x); } dfs(1, 0); dfs2(1, 0); printf("%lld\n", ans / 2); return 0; } void dfs2(ll n, ll ff) { ll t[7] = {0}; if (ff) { for (ll i = 1; i < K; i++) { t[i] = f[ff][i] - f[n][i-1]; } t[0] = f[ff][0] - f[n][K-1] - siz[n]; for (ll i = 1; i < K; i++) { f[n][i] += t[i-1]; } f[n][0] += t[K-1] + (N - siz[n]); } ans += f[n][0]; for (ll i = head[n]; ~i; i = E[i].nt) { ll v = E[i].to; if (v == ff) continue; else { dfs2(v, n); } } } void dfs(ll n, ll ff) { siz[n] = 1; for (ll i = head[n]; ~i; i = E[i].nt) { ll v = E[i].to; if (v == ff) continue; else { dfs(v, n); siz[n] += siz[v]; f[n][0] += f[v][K-1] + siz[v]; for (ll i = 1; i < K; i++) { f[n][i] += f[v][i-1]; } } } } void add(ll x, ll y) { cnt++; E[cnt].to = y; E[cnt].nt = head[x]; head[x] = cnt; } /* 6 2 1 2 1 3 2 4 2 5 4 6 ans :20 6 1 1 2 1 3 2 4 2 5 4 6 ans :31 7 2 1 2 2 3 3 4 4 5 5 6 6 7 ans :34 */