Codeforces Round #778

Codeforces Round #778 D. Potion Brewing Class

给定若干的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;
}
posted @ 2022-03-21 21:49  lmj_1  阅读(46)  评论(0)    收藏  举报