给定若干的a[i]/a[j]=x/y关系,请确定解以满足所有a[i]都是正整,且所有数和最小,
解法:从n-1对关系可以看出,要唯一确定所有数,那么所有关系肯定满足一棵树形关系,我们要求最小解,就从节点1做下去,将每个数求出来,我们设第一个数是1,最后求出来的解对于每个点可能是一个分数,所以还需要求出分子的最小公倍数,才能将每个数变为整数,但是考虑到直接求的话,每个数会很大,无法直接求解最小公倍数,我们考虑到,一堆数的最小公倍数等于将其质因数分解以后,每个质因子的最大指数相乘,比如4=22,9=32 ,6=2*3,所以最小公倍数就是22*32=36,固我们只需要将树上每对关系做质因数分解,并且对分子分母化简,求出每个质因子的幂次最大值就可以了,先将质因子分解出来,那么对于分解质因数的总复杂度就是nlogn
点击查看代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=4e5+10;
int Head[maxn],Next[maxn*2],ver[maxn*2],edge1[maxn*2],edge2[maxn*2];
int tot;
int v[maxn],mp[maxn],pr[maxn];
vector<int>Prime;
ll ans=0;
void Insert(int u,int v,int w1,int w2){
ver[++tot]=v;
Next[tot]=Head[u];
Head[u]=tot;
edge1[tot]=w1;
edge2[tot]=w2;
}
void init(int n){
tot=0;
for (int i=0;i<=2*n;i++) Head[i]=Next[i]=ver[i]=edge1[i]=edge2[i]=0;
}
void prime(){
for (int i=2;i<=maxn-10;i++){
if(v[i]==0){
v[i]=i;
Prime.push_back(i);
}
for (auto x:Prime){
if(x>v[i] || x>(maxn-10)/i) break;
v[i*x]=x;
}
}
}
map<int,int> get_prime(int x){
map<int,int>p;
for (auto v:Prime){
if(v*v>x) break;
if(x%v==0){
p[v]=0;
while(x%v==0) {x/=v;p[v]=p[v]+1;}
}
}
if(x>1) p[x]=1;
return p;
}
void dfs(int x,int fa){
for (int i=Head[x];i;i=Next[i]){
int v=ver[i];
if(v==fa) continue;
map<int,int>yz1=get_prime(edge1[i]);
map<int,int>yz2=get_prime(edge2[i]);
for (auto xx:yz2) pr[xx.first]+=xx.second;
for (auto xx:yz1) {
pr[xx.first]-=xx.second;
if(pr[xx.first]<0) mp[xx.first]=max(mp[xx.first],-pr[xx.first]);
}
dfs(v,x);
for (auto xx:yz2) pr[xx.first]-=xx.second;
for (auto xx:yz1) pr[xx.first]+=xx.second;
}
}
ll quickpow(ll a,ll b){
ll ans=1;
for (;b;b>>=1){
if(b&1) ans=ans*a%mod;
a=a*a%mod;
}
return ans;
}
void dfs2(int x,int fa,ll a){
for (int i=Head[x];i;i=Next[i]){
int v=ver[i];
if(v==fa) continue;
ll p=a*edge2[i]%mod*quickpow(edge1[i],mod-2)%mod;
ans=(ans+p)%mod;
dfs2(v,x,p);
}
}
int main(){
#ifdef lmj_debug
freopen("1.in","r",stdin);
#endif
prime();
int T;
cin>>T;
while(T--){
int n;
cin>>n;
init(n);
for (int i=1;i<n;i++){
int u,v,w1,w2;
scanf("%d%d%d%d",&u,&v,&w1,&w2);
Insert(u,v,w1,w2);
Insert(v,u,w2,w1);
}
dfs(1,1);
ll Lcm=1;
for (auto x:Prime){
if(mp[x]) {Lcm=Lcm*quickpow(x,mp[x])%mod;pr[x]=mp[x]=0;}
}
ans=Lcm;
//cout<<Lcm<<endl;
dfs2(1,1,Lcm);
printf("%lld\n",ans);
}
return 0;
}