题解:P10894 虚树
SunsetVoice · · 题解
好题啊(赞赏)
然后自信提交,获得了
30 分的好成绩。
设
显然,如果要跨子树选择,必须选
若不选
转移都是
然后自信提交,获得了
30 分的好成绩。
这里有一个小优化,显然一次改变
然后自信提交,获得了
30 分的好成绩。
复杂度仍是
我们考虑树上前缀积算子树贡献系数
于是答案为
复杂度为
#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
int siz[500001] = {0},n,m,dp[500001][2] = {0},db = 0;
int fdp[500001][2] = {0};
vector<int>e[500001];
int vis[500001] = {0};
const int mod = 998244353;
int fa[500001] = {0};
int g[500001] = {0};
int qpow(int x,int y){
int ret = 1;
while(y){
if(y&1){
ret*=x;
ret%=mod;
}
x*=x;
x%=mod;
y>>=1;
}
return ret;
}
void dfs(int pos){
vis[pos] = 1;
int dyc = 1;
for(int i = 0;i<e[pos].size();i++){
if(!vis[e[pos][i]]){
fa[e[pos][i]] = pos;
//cout<<pos<<" "<<e[pos][i]<<endl;
dfs(e[pos][i]);
dp[pos][0]+=dp[e[pos][i]][0]+dp[e[pos][i]][1];
dp[pos][0]%=mod;
//cout<<dp[e[pos][i]][0]+dp[e[pos][i]][1]+1<<endl;
dyc*=(dp[e[pos][i]][0]+dp[e[pos][i]][1]+1)%mod;
dyc%=mod;
}
}
dp[pos][1]+=dyc;
dp[pos][1]%=mod;
for(int i = 0;i<e[pos].size();i++){
if(e[pos][i]!=fa[pos]){
g[e[pos][i]] = dp[pos][1]*qpow(dp[e[pos][i]][1]+dp[e[pos][i]][0]+1,mod-2)%mod+1;
}
}
return;
}
void dfs2(int pos){
if(fa[pos]!=1){
g[pos]*=g[fa[pos]];
g[pos]%=mod;
}
for(int i = 0;i<e[pos].size();i++){
if(e[pos][i]!=fa[pos]){
dfs2(e[pos][i]);
}
}
return;
}
signed main(){
cin>>n;
for(int i = 1;i<n;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
for(int i = 1;i<=n;i++){
dp[i][0] = 0;
dp[i][1] = 0;
}
dfs(1);
dfs2(1);
// for(int i = 1;i<=n;i++){
// cout<<g[i]<<" ";
// }
// cout<<endl;
cin>>m;
for(int i = 1;i<=m;i++){
int pos;
cin>>pos;
cout<<(dp[1][0]+dp[1][1]+mod-g[pos]*(dp[pos][0]+dp[pos][1])%mod)%mod<<endl;;
}
return 0;
}