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;
}
posted @ 2022-08-07 09:53  Code_AC  阅读(42)  评论(0编辑  收藏  举报