Potion Brewing Class(CF 1654 D)

传送门

题目大意

t组询问,每组询问给你一棵有n个节点,n1条边的树,树上每两个相连点之间的权值成比例,每组询问问所有权值都是整数且最小时的权值和,答案对998244353取模。(1t104,2n2105,n2105)

思路

首先很容易想到dfs一下然后从叶子节点传答案上来,但是发现不是能写,于是就换一个思路。这次我们设根节点的权值是1,然后往下dfs,于是就可以得到n个最简分数,然后约个分就结束了。但是再仔细想一想,真的嘛?很容易又能想到分母还是会很大然后爆long long,然后就会寄。所以我们又能想到一次一次更新,每到达一个新的点,我们可以分别对分子分母进行质因子分解,然后记一个a[i]b[i]分别表示质因子i的个数和质因子i出现过的最多次数,对于分母的质因子,我们在原基础上加上他们的个数,对于分子就减去,然后最后就可以先把每个点对于模数取模后的值加起来,然后再乘上分母的LCM,然后这道题就能轻松AC啦!

代码

#include<bits/stdc++.h>
using namespace std;
long long mod=998244353;
const int maxn=200005;
struct EDGE
{
    int next,to,x,y;
}edge[maxn<<1];
int head[maxn];
int cnt;
void add(int u,int v,int x,int y)
{
    edge[cnt].x=x;
    edge[cnt].y=y;
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
long long a[200005],b[200005];
long long poww(long long a,long long n)
{
	long long ans=1;
	while(n)
	{
		if(n&1)ans=ans*a%mod;
		a=a*a%mod;
		n>>=1;
	}
	return ans;
}
int main()
{
	memset(head,-1,sizeof(head));
	int _;
	scanf("%d",&_);
	while(_--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<n;i++)
		{
			int u,v,x,y;
			scanf("%d%d%d%d",&u,&v,&x,&y);
			add(u,v,x,y);
			add(v,u,y,x);
		}
		int maxx=0;
		long long tot=0;
		function<void(int,int)>update=[&](int x,int w)
		{
			for(int i=2;i*i<=x;i++)
			{
				while(x%i==0)
				{
					a[i]+=w;
					x/=i;
				}
				if(a[i]>b[i])
				{
					b[i]=a[i];
					maxx=max(maxx,i);
				}
			}
			if(x!=1)
			{
				a[x]+=w;
				if(a[x]>b[x])
				{
					b[x]=a[x];
					maxx=max(maxx,x);
				}
			}
		};
		function<void(int,int,long long)>dfs=[&](int s,int fa,long long val)
		{
			tot=(tot+val)%mod;
			for(int i=head[s];~i;i=edge[i].next)
			{
				int it=edge[i].to,x=edge[i].x,y=edge[i].y;
				if(it==fa)continue;
				update(y,-1);
				update(x,1);
				dfs(it,s,val*y%mod*poww(x,mod-2)%mod);
				update(x,-1);
				update(y,1);
			}
		};
		dfs(1,0,1);
		for(int i=2;i<=maxx;i++)
		{
			if(b[i])
			{
				tot=tot*poww(i,b[i])%mod;
				b[i]=0;
			}
		}
		printf("%lld\n",tot);
		if(_)
		{
			for(int i=1;i<=cnt;i++)
				edge[i]={0,0,0,0};
			for(int i=1;i<=n;i++)
				head[i]=-1;
			cnt=0;
		}
	}
	return 0;
}

__EOF__

本文作者Jerry-Black
本文链接https://www.cnblogs.com/Jerry-Black/p/16036873.html
关于博主:小蒟蒻一只( ̄^ ̄)ゞ
版权声明:转载请注明来源哟~ QAQ
声援博主:UP UP UP !!!
posted @   Jerry_Black  阅读(133)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示