[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;
}
posted @ 2021-08-25 22:12  zkdxl  阅读(46)  评论(2编辑  收藏  举报