CF371B题解
题目翻译:
给你两个数 \(a,b\),每次操作可选择删除其中任意一个数的一部分,规则如下:
-
若改变的数为 \(2\) 的倍数,则可删去此数的 \(\frac{1}{2}\)。
-
若改变的数为 \(3\) 的倍数,则可删去此数的 \(\frac{2}{3}\)。
-
若改变的数为 \(5\) 的倍数,则可删去此数的 \(\frac{4}{5}\)。
现问你将两数化为相同需要的最少操作次数。
题目分析:
显然,删去 \(\frac{1}{2}\) 相当于乘 \(\frac{1}{2}\),删去 \(\frac{2}{3}\) 相当于乘 \(\frac{1}{3}\),删去 \(\frac{4}{5}\) 相当于乘 \(\frac{1}{5}\)。
那么很显然,若要操作次数最少,那么最后化成的相同的数必定是 \(a,b\) 两数的 gcd,即最大公因数。
那么思路就出来了:
1. 将 \(a,b\) 两数的 gcd 求出;
2. 计算将两数各自变为这个 gcd 需要多少次操作;
3. 将两数所要的操作求和得答案。
(思路正确性可保证)
注:
看到 \(1 \leqslant a,b \leqslant 10^9\),就知道要开 long long。
且这里还需要特判两种情况:
1. 若开始两数就相同,那么输出 \(0\)。
2. 若在变为 gcd 的过程中,无法通过除以 \(2,3,5\) 来得到,即出现了非 \(2,3,5\) 的因数,那么输出 \(-1\)。
这里给出核心部分代码:
signed main()
{
a=read(),b=read();
if(a==b)
{
printf("0\n");
return 0;
}
int c=gcd(a,b);
int d=a/c,f=b/c;
while(d%2==0)
{
d/=2;
ans1++;
}
while(d%3==0)
{
d/=3;
ans1++;
}
while(d%5==0)
{
d/=5;
ans1++;
}
while(f%2==0)
{
f/=2;
ans2++;
}
while(f%3==0)
{
f/=3;
ans2++;
}
while(f%5==0)
{
f/=5;
ans2++;
}
if(d!=1 || f!=1)
{
printf("-1\n");
return 0;
}
ans=ans1+ans2;
printf("%lld\n",ans);
return 0;
}