关于此题CF2040E Control of Randomness 的一些总结[树形DP][概率DP]
题目大意:给定一棵树和q个询问,每个询问给定
思路:对于每个奇数步数很简单,而对于每个偶数步数的情况,我们需要推一下式子。假设当前要走的是第偶数步,并且当前所处节点的度是
其中
要求这个式子,我们先把它拆开:
对于后半部分直接用等比数列求和公式即可求出是
我们对两边同时求导有
由于
代码:
#include<bits/stdc++.h>
using namespace std;
const long long mod = 998244353;
long long t;
const long long N = 2e5 + 10;
long long n,q,in[N],dep[N];
long long head[N],tot,ans,step;
bool flag;
struct node {
long long v,next;
}cnt[N];
priority_queue<long long> vt;
void insert(long long u,long long v) {
cnt[++tot].v = v;
cnt[tot].next = head[u];
head[u] = tot;
}
void dfs1(long long u,long long fa) {
dep[u] = dep[fa] + 1;
for(long long i = head[u];i;i = cnt[i].next) {
if(cnt[i].v == fa) continue;
dfs1(cnt[i].v,u);
}
}
void dfs2(long long u,long long fa,long long tg) {
if(u == tg) {
flag = true;
vt.push(1);
step++;
return;
}
for(long long i = head[u];i;i = cnt[i].next) {
if(cnt[i].v == fa) continue;
dfs2(cnt[i].v,u,tg);
if(flag == true) {
if(u != 1) {
step++;
if(step % 2 != 0) vt.push(1);
else vt.push((2 * in[u] - 1) % mod);
}
return;
}
}
}
void solve() {
for(long long i = 0;i <= n;i++) head[i] = dep[i] = in[i] = 0;
for(long long i = 0;i <= tot;i++) cnt[i].v = cnt[i].next = 0;
tot = 0;
cin >> n >> q;
for(long long u,v,i = 1;i < n;i++) {
cin >> u >> v;
insert(u,v);
insert(v,u);
in[u]++;
in[v]++;
}
dfs1(1,0);
for(long long v,p,i = 1;i <= q;i++) {
cin >> v >> p;
ans = flag = step = 0;
dfs2(1,0,v);
while(!vt.empty()) {
if(vt.top() > 1 && p > 0)
ans++,p--;
else ans += vt.top();
vt.pop();
ans %= mod;
}
cout << ans << '\n';
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--) solve();
return 0;
}
分类:
做题总结