[CF986E] Prince's Problem
\(\text{Problem}:\)Prince's Problem
\(\text{Solution}:\)
套路的,把询问拆成若干条从 \(1\rightarrow u\) 的路径。
在 \(1\rightarrow u\) 的路径上,对于质数 \(p\) 与指数 \(k\)(\(k\geq 1\)),记录 \(p^{k}\) 的出现次数。然后处理挂在点 \(u\) 上的询问。具体的,对询问值 \(x\) 也进行质因数分解,对于其每个质因数 \(p\),统计 \(p^{k}\) 对答案的贡献即可。
如采用朴素的 \(O(\sqrt V)\) 分解质因数方法,我们需要进行 \(n+4q\) 次,其复杂度难以接受。可以对每个值在线性筛时记下其最大质因子,这样就可以在 \(O((n+4q)\log V)\) 的时间复杂度内完成质因数分解的操作。
不是我说,这套路题放到现在真的有 *2800 吗
\(\text{Code}:\)
#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#define int long long
#define ri register
#define mk make_pair
#define fi first
#define se second
#define pb push_back
#define eb emplace_back
#define is insert
#define es erase
#define vi vector<int>
#define vpi vector<pair<int,int>>
using namespace std; const int N=100010, M=10000000, Mod=1e9+7;
inline int read()
{
int s=0, w=1; ri char ch=getchar();
while(ch<'0'||ch>'9') { if(ch=='-') w=-1; ch=getchar(); }
while(ch>='0'&&ch<='9') s=(s<<3)+(s<<1)+(ch^48), ch=getchar();
return s*w;
}
int pri[M/10+5],cnt,val[M+5],r[M+5]; bool book[M+5];
int n,Q,a[N],f[N],d[N],siz[N],son[N],top[N],id[N],nowid;
vpi q[N<<2]; int ans[N];
int head[N],maxE; struct Edge { int nxt,to; }e[N<<1];
inline void Add(int u,int v) { e[++maxE].nxt=head[u]; head[u]=maxE; e[maxE].to=v; }
inline int ksc(int x,int p) { int res=1; for(;p;p>>=1, x=1ll*x*x%Mod) if(p&1) res=1ll*res*x%Mod; return res; }
inline void Init()
{
for(ri int i=2;i<=M;i++)
{
if(!book[i]) pri[++cnt]=i, r[i]=i;
for(ri int j=1;j<=cnt&&i*pri[j]<=M;j++)
{
book[i*pri[j]]=1, r[i*pri[j]]=pri[j];
if(i%pri[j]==0) break;
}
}
}
void DFS1(int x,int fa)
{
f[x]=fa, d[x]=d[fa]+1, siz[x]=1;
for(ri int i=head[x];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
DFS1(v,x);
siz[x]+=siz[v];
if(siz[v]>siz[son[x]]) son[x]=v;
}
}
void DFS2(int x,int topf)
{
top[x]=topf, id[x]=++nowid;
if(!son[x]) return;
DFS2(son[x],topf);
for(ri int i=head[x];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==f[x]||v==son[x]) continue;
DFS2(v,v);
}
}
inline int LCA(int x,int y)
{
while(top[x]^top[y])
{
if(d[top[x]]<d[top[y]]) swap(x,y);
x=f[top[x]];
}
if(d[x]>d[y]) swap(x,y);
return x;
}
void DFS3(int x,int fa)
{
int w=a[x];
while(w>1)
{
int o=1,now=r[w];
while(w%now==0) o*=now, w/=now, val[o]++;
}
for(auto i:q[x])
{
int w=abs(i.fi);
int pd=1;
while(w>1)
{
int o=1,now=r[w],ti=0;
while(w%now==0) o*=now, w/=now, ti+=val[o];
pd=1ll*pd*ksc(now,ti)%Mod;
}
if(i.fi<0) pd=ksc(pd,Mod-2);
ans[i.se]=1ll*ans[i.se]*pd%Mod;
}
for(ri int i=head[x];i;i=e[i].nxt)
{
int v=e[i].to;
if(v==fa) continue;
DFS3(v,x);
}
w=a[x];
while(w>1)
{
int o=1,now=r[w];
while(w%now==0) o*=now, w/=now, val[o]--;
}
}
signed main()
{
Init();
n=read();
for(ri int i=1;i<n;i++)
{
int u,v;
u=read(), v=read();
Add(u,v), Add(v,u);
}
DFS1(1,0), DFS2(1,1);
for(ri int i=1;i<=n;i++) a[i]=read();
Q=read();
for(ri int i=1;i<=Q;i++)
{
int x,y,w;
x=read(), y=read(), w=read();
int tt=LCA(x,y);
q[x].eb(mk(w,i));
q[y].eb(mk(w,i));
q[tt].eb(mk(-w,i));
if(f[tt]) q[f[tt]].eb(mk(-w,i));
ans[i]=1;
}
DFS3(1,0);
for(ri int i=1;i<=Q;i++) printf("%d\n",ans[i]);
return 0;
}
夜畔流离回,暗叹永无殿。
独隐万花翠,空寂亦难迁。
千秋孰能为,明灭常久见。
但得心未碎,踏遍九重天。