题解:P8973 『GROI-R1』 继续深潜,为了同一个梦想
换根 dp 模板题。
当
简单解释一下,
加一是因为要加上集合为
换根的时候根据上面的公式改下
具体实现看代码。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read() {
int s = 0, w = 1;
char c = getchar();
while (!isdigit(c)) {
if (c == '-')
w = -w;
c = getchar();
}
while (isdigit(c)) {
s = s * 10 + c - 48;
c = getchar();
}
return s * w;
}
void pr(int x) {
if (x < 0)
putchar('-'), x = -x;
if (x > 9)
pr(x / 10);
putchar(x % 10 + 48);
}
#define end_ putchar('\n')
#define spc_ putchar(' ')
const int maxN = 5e5 + 7, mod = 1e9 + 7;
const int m2 = 500000004;
// 2 的逆元
int n;
vector<int> E[maxN];
int f[maxN], s[maxN], A[maxN], ans;
// s 数组是预处理公式中求和的部分, A[i] 为 ans[i]
int C(int x) {
return x * (x - 1 + mod) % mod * m2 % mod;
}
void dfs(int x, int fa) {
for (int to : E[x])
if (to != fa) {
dfs(to, x);
f[x] += f[to] * 2 + 1;
f[x] %= mod;
s[x] += C(f[to] * 2 + 1);
s[x] %= mod;
}
}
int ff[maxN];
void calc(int x, int fa) {
A[x] = ((C(f[x]) - s[x] + mod) % mod + f[x]) % mod;
for (int to : E[x]) {
if (to == fa)
continue;
int fx = f[x], fto = f[to];
int S = s[to];
f[x] -= f[to] * 2 + 1;
f[x] = (f[x] + mod * 2) % mod;
// 这里要注意乘 2,因为上面的 f[to] 乘 2 了,只加一个 mod 有可能不够。
f[to] += f[x] * 2 + 1;
f[to] %= mod;
s[to] += C(f[x] * 2 + 1);
s[to] %= mod;
calc(to, x);
f[x] = fx, f[to] = fto;
s[to] = S;
}
}
signed main() {
n = read();
for (int i = 1; i < n; i++) {
int u = read(), v = read();
E[u].emplace_back(v);
E[v].emplace_back(u);
}
dfs(1, 0);
calc(1, 0);
for (int i = 1; i <= n; i++)
ans ^= A[i] * i;
pr(ans), end_;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 推荐几款开源且免费的 .NET MAUI 组件库
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· Trae初体验