求助今天下午比赛T2 WA 0pts
  • 板块学术版
  • 楼主masonpop
  • 当前回复4
  • 已保存回复4
  • 发布时间2023/1/27 19:10
  • 上次更新2023/10/24 02:55:35
查看原帖
求助今天下午比赛T2 WA 0pts
614725
masonpop楼主2023/1/27 19:10

rt.思路是先去掉小数点,考虑路径上数相乘后末尾 00 的个数,我是维护 2255 的幂次取较小者。然后记录总小数点偏移量,比较两者大小。好像都可以通过 LCA\text{LCA} 简单计算。但是始终只能过一个点。求 hack/求调。

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=400010;
const int maxm=500010;
int n,m,x,y,tot=0;
int a[maxn],head[maxn],to[maxm],nxt[maxm];
int dep[maxn],fa[maxn][25],lg[maxn],cnt[maxn],ver[maxn];
double z;
inline int calc2(int x)//2的幂次
{
	int cal=0;
	while(x && x%2==0)cal++,x/=2;
	return cal;	
} 
inline int calc5(int x)//5的幂次
{
	int cal=0;
	while(x && x%5==0)cal++,x/=5;
	return cal;	
} 
int sum[maxn],two[maxn],five[maxn];//sum:总小数点位数,two,five:末尾0的个数 
inline void add(int x,int y,int z,int p)//p:小数点位数 
{
	to[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;//模板 
	ver[tot]=z;
	cnt[tot]=p;
}
inline void dfs(int x,int f)
{
	dep[x]=dep[f]+1;
	fa[x][0]=f;
	for(int i=1;(1<<i)<=dep[x];i++)
	{
		fa[x][i]=fa[fa[x][i-1]][i-1];
	}
	for(int i=head[x];i;i=nxt[i])
	{
		int y=to[i];
		if(y==f)continue;
		sum[y]=sum[x]+cnt[i];
		two[y]=two[x]+calc2(ver[i]);
		five[y]=five[x]+calc5(ver[i]);
		dfs(y,x);
	}
}
inline int LCA(int x,int y)
{
	if(dep[x]<dep[y])swap(x,y);
	while(dep[x]>dep[y])x=fa[x][lg[dep[x]-dep[y]]-1];
	if(x==y)return x;
	for(int i=lg[dep[x]];i>=0;i--)
	{
		if(fa[x][i]!=fa[y][i])
		{
			x=fa[x][i];
			y=fa[y][i];
		}
	}
	return fa[x][0];
}
signed main()
{
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
    for(int i=1;i<n;i++)
    {
    	scanf("%lld%lld%lf",&x,&y,&z);
    	int p=0;
    	while(z!=floor(z))z*=10,p++;//小数点位数 
    	add(x,y,(int)z,p);
		add(y,x,(int)z,p);
	}
	dfs(1,0);
	for(int i=1;i<=n;++i)
	{
		lg[i]=lg[i-1]+(1<<lg[i-1]==i);//预处理log 
	} 
	while(m--)
	{
		scanf("%lld%lld",&x,&y);
		int flo=sum[x]+sum[y]-2*sum[LCA(x,y)];
		int twos=two[x]+two[y]-2*two[LCA(x,y)]+calc2(a[x]);
		int fives=five[x]+five[y]-2*five[LCA(x,y)]+calc5(a[x]);
		int ten=min(twos,fives);
		if(ten>=flo)printf("Yes\n");
		else printf("No\n");
	}
    return 0;
}
/*
in:
5 5
7 8 10 1 4
1 2 0.1
2 3 0.4
3 4 0.25
4 5 0.4
1 2
2 4
1 3
3 5
1 5

out:
No
No
No
Yes
No
*/
2023/1/27 19:10
加载中...