刀工对决
题目链接: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;
} 
京公网安备 11010502036488号