题解
验题人题解。
考虑对于一个
那我们相当于要对每个
容易发现计算
看到这个贡献形式我们首先想到丢到 01-Trie 上面计算贡献。考虑在 dfs 的同时对每个点维护一个 Trie 作为子树内的贡献信息,合并时考虑类似于线段树合并地合并两棵 Trie。
枚举
计算
这样就做完了,时间复杂度是
#include<bits/stdc++.h>
#define pii pair<int,int>
#define x first
#define y second
#define pb push_back
using namespace std;
const int N = 2e5 + 7;
int tr[N*30][2],sum[N*30];
int num;
int rt[N];
int n,q,mod,r;
vector<int>a[N];
int b[30][2];
int s[N],pl[N],pr[N];
int d[N];
void add(int &x,int y){x += y; if(x>=mod) x -= mod;}
int tmp[30];
void ins(int val,int id){
int p = id;
memset(tmp,0,sizeof tmp);
for(int i=0;i<=20;++i){
int x = (val >> i) & 1;
if(!tr[p][x]) tr[p][x] = ++num;
tmp[i] = b[i][x];
p = tr[p][x];
}
for(int i=19;i>=0;--i) tmp[i] = 1ll * tmp[i+1] * tmp[i] % mod;
p = id;
for(int i=0;i<=20;++i){
int x = (val >> i) & 1;
add(sum[p],tmp[i]);
p = tr[p][x];
}
}
int merge(int x,int y){
if(!x) return y;
if(!y) return x;
add(sum[x],sum[y]);
tr[x][0] = merge(tr[x][0],tr[y][0]);
tr[x][1] = merge(tr[x][1],tr[y][1]);
return x;
}
void del(int x,int i){
swap(tr[x][0],tr[x][1]);
if(tr[x][1]) del(tr[x][1],i+1);
sum[x] = 1ll * sum[tr[x][0]] * b[i][0] % mod;
add(sum[x],1ll * sum[tr[x][1]] * b[i][1] % mod);
}
void dfs(int x,int fa){
d[x] = d[fa] + 1;
if(!rt[x]) rt[x] = ++num;
for(auto c:a[x]){
if(c==fa) continue;
dfs(c,x);
rt[x] = merge(rt[x],rt[c]);
}
ins(x+d[x],rt[x]);
pl[x] = sum[rt[x]];
del(rt[x],0);
pr[x] = sum[rt[x]];
}
void calc(int x,int fa){
s[x] = s[fa];
add(s[x],pl[x]);
if(x!=r) add(s[x],mod-pr[x]);
for(auto c:a[x]){
if(c==fa) continue;
calc(c,x);
}
}
void solve(){
memset(s,0,sizeof s);
memset(tr,0,sizeof tr);
memset(rt,0,sizeof rt);
memset(d,0,sizeof d);
memset(sum,0,sizeof sum);
num = 0;
dfs(r,0);
calc(r,0);
long long ans = 0;
for(int i=1;i<=n;++i) ans ^= 1ll * i * s[i];
cout<<ans<<'\n';
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(nullptr);
cout.tie(nullptr);
cin>>n;
for(int i=1;i<n;++i){
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
cin>>q;
while(q--){
cin>>r>>mod;
for(int i=0;i<=20;++i) cin>>b[i][0];
for(int i=0;i<=20;++i) cin>>b[i][1];
solve();
}
return 0;
}