刀工对决

题目链接:nowcoder 217128

到主站看:https://blog.csdn.net/weixin_43346722/article/details/116243367

题目大意

给你两个数,你可以对它们进行两种操作,除以三或除以五分之三。
问你能否通过这两个操作把它们变成一样的数,如果可以输出最小次数。

思路

这道题我们观察一下两个操作的性质。

第一个操作: 变成

第二个操作: 变成

那你会发现,如果你做两个操作各一次,就是 变成

那你会想到,你要让两个数变成一样,那就是可以把它们 GCD 以外的东西都除成 1。
这其实有一点点贪心的感觉,就是你如果把 GCD 的除了,那两边都要除,而且你除不除都是一样,那还不如不除。

那你看到除 会出 ,那你可以先把 GCD 外的 都除完(记得乘 ),然后接着就把 GCD 外的 都除完。
记得第二次除的时候要重新算 GCD,因为你乘了 ,可能刚好另外一边也有多的 ,这个 就不用除了。

然后如果最后 GCD 外还有数,就说明无解,否则就是你前面除的次数。

代码

#include<cstdio>
#define ll long long

using namespace std;

int n;
ll ans, a, b, gcd;

ll GCD(ll x, ll y) {
    if (!y) return x;
    return GCD(y, x % y);
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%lld %lld", &a, &b);

        ll gcd = GCD(a, b);//先除以一次gcd
        a /= gcd;
        b /= gcd;

        while (a % 5 == 0) {//弄五分之三的
            a = a / 5 * 3;
            ans++;
        }
        while (b % 5 == 0) {
            b = b / 5 * 3;
            ans++;
        }

        gcd = GCD(a, b);//再除一次gcd
        a /= gcd;
        b /= gcd;

        while (a % 3 == 0) {//处理三分之一的
            a = a / 3;
            ans++;
        }
        while (b % 3 == 0) {
            b = b / 3;
            ans++;
        }

        if (a != b) {
            printf("-1");
            return 0;
        }
    }

    printf("%lld", ans);

    return 0;
}