Description
Solution
假设到
u
u
u不超过
d
d
d的点的权值分解质因数的质数集合为
p
p
p,答案就是要求
∑
i
=
1
∣
p
∣
p
i
k
i
\sum\limits_{i=1}^{|p|} p_i^{k_i}
i=1∑∣p∣piki。
这个很不好处理,考虑把一个
p
k
p^k
pk拆成
p
,
p
2
,
p
3
,
⋯
 
,
p
k
p,p^2,p^3,\cdots,p^k
p,p2,p3,⋯,pk中颜色,每种颜色的贡献都为
p
p
p,那么题目转化成为到
u
u
u不超过
d
d
d的点中颜色至少出现一次的贡献积。那么就是经典问题了,可以对每种颜色维护
d
f
s
dfs
dfs序,在线段树上修改。至于这题,只要按深度开可持久化线段树即可,查询相当于在
d
e
p
u
+
d
dep_u+d
depu+d的线段树上查询
u
u
u的子树。
关于颜色的维护具体可以见这里。
Code
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<set>
#include<vector>
#define fo(i,j,k) for(int i=j;i<=k;++i)
#define fd(i,j,k) for(int i=j;i>=k;--i)
#define rep(i,x) for(int i=ls[x];i;i=nx[i])
using namespace std;
typedef long long ll;
const int N=1e5+10,M=2e5+10,S=1e7+10,mo=998244353;
typedef multiset<int> :: iterator it;
int to[M],nx[M],ls[N],num=0;
void link(int u,int v){
to[++num]=v,nx[num]=ls[u],ls[u]=num;
}
int bg[S],tt=0,tot=0;
multiset<int> cl[N*24];
int L[N],R[N],f[N][17],dep[N],z[N],n;
vector<int> dz[N];
int a[N];
int qpow(int x,int y){
int s=1;
for(;y;y>>=1,x=(ll)x*x%mo) if(y&1) s=(ll)s*x%mo;
return s;
}
void pre(int x,int fr){
z[L[x]=++tot]=x;
f[x][0]=fr,dep[x]=dep[fr]+1;
fo(i,1,16) f[x][i]=f[f[x][i-1]][i-1];
rep(i,x) if(to[i]!=fr) pre(to[i],x);
R[x]=tot;
}
int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v);
fd(i,16,0) if(dep[f[u][i]]>=dep[v]) u=f[u][i];
if(u==v) return u;
fd(i,16,0) if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i];
return f[u][0];
}
int pr[S/15],sm[S];
int mx=0;
void pre0(){
fo(i,2,mx){
if(!sm[i]) sm[i]=i,pr[++pr[0]]=i;
fo(j,1,pr[0]){
int t=i*pr[j];
if(t>mx) break;
sm[t]=pr[j];
if(i%pr[j]==0) break;
}
}
}
int d[50];
void find(int x){
if(x==1) return;
d[++d[0]]=sm[x],find(x/sm[x]);
}
int rt[N];
void mul(int &x,int y) {x=(ll)(!x?1:x)*y%mo;}
struct node{
int v,l,r,s;
}tr[N*110];
int be[N*110];
int now;
void ins(int x,int t,int &v,int l=1,int r=n){
if(be[v]!=now){
tr[++tot]=tr[v],v=tot;
be[v]=now;
}
mul(tr[v].s,t);
if(l==r) return;
int mid=(l+r)>>1;
x<=mid?ins(x,t,tr[v].l,l,mid):ins(x,t,tr[v].r,mid+1,r);
}
int prod(int x,int y,int v,int l=1,int r=n){
if(!v) return 1;
if(l>=x && r<=y) return !tr[v].s?1:tr[v].s;
int mid=(l+r)>>1,t=1;
if(x<=mid) mul(t,prod(x,y,tr[v].l,l,mid));
if(y>mid) mul(t,prod(x,y,tr[v].r,mid+1,r));
return t;
}
int get(int x){
if(!bg[x]){
bg[x]=++tt;
cl[tt].insert(0),cl[tt].insert(n+1);
}
return bg[x];
}
void modify(int t,int cc,int x){
int col=get(cc),nt=qpow(t,mo-2);
ins(L[x],t,rt[now]);
cl[col].insert(L[x]);
it pos=cl[col].find(L[x]);
it p=pos,q=pos;--p,++q;
if(*p && *q<=n) ins(L[lca(z[*p],z[*q])],t,rt[now]);
if(*q<=n) ins(L[lca(z[*pos],z[*q])],nt,rt[now]);
if(*p) ins(L[lca(z[*pos],z[*p])],nt,rt[now]);
}
void add(int x){
d[0]=0,find(a[x]);
fo(i,1,d[0]){
int r=i,w=1,p=d[i];
for(;r<d[0] && d[r+1]==p;++r);
fo(j,i,r) w=(ll)w*p%mo,modify(p,w,x);
i=r;
}
}
int main()
{
freopen("half.in","r",stdin);
freopen("half.out","w",stdout);
int tp;
scanf("%d %d",&tp,&n);
fo(i,1,n) scanf("%d",&a[i]),mx=max(mx,a[i]);
fo(i,2,n){
int u,v;
scanf("%d %d",&u,&v);
link(u,v),link(v,u);
}
pre0(),pre(1,0),tot=0;
fo(i,1,n) dz[dep[i]].push_back(i);
fo(i,1,n){
now=i,rt[i]=rt[i-1];
int o=dz[i].size();
fo(j,0,o-1) add(dz[i][j]);
}
int q,ans=0;
scanf("%d",&q);
for(;q--;){
int u,t;
scanf("%d %d",&u,&t),u^=tp*ans,t^=tp*ans;
ans=prod(L[u],R[u],rt[min(dep[u]+t,n)]);
printf("%d\n",ans);
}
}