兩個矩形 (a₁,b₁), (a₂,b₂)。操作:1) 某邊 ÷2(需能被 2 整除);2) 某邊 ×2/3(需能被 3 整除)。求最少操作使面積相等,並輸出最終邊長。
操作本質:
// 分解函數
pair<int,int> count_23(long long x) {
int c2 = 0, c3 = 0;
while (x % 2 == 0) { x /= 2; c2++; }
while (x % 3 == 0) { x /= 3; c3++; }
return {c2, c3, x}; // 返回 (c2, c3, rest)
}
需增加 2 的個數 → 對應矩形執行操作 2(÷3×2)
需減少 2 的個數 → 對應矩形執行操作 1(÷2)
需增加 3 的個數 → 不可能(操作只能減少 3)
需減少 3 的個數 → 執行操作 2(÷3×2),同時增加 2
#include <bits/stdc++.h>
using namespace std;
struct Rect {
long long a, b;
int c2, c3;
long long rest;
};
Rect decompose(long long a, long long b) {
Rect r; r.a = a; r.b = b;
auto [c2a, c3a, rsta] = count_23(a);
auto [c2b, c3b, rstb] = count_23(b);
r.c2 = c2a + c2b;
r.c3 = c3a + c3b;
r.rest = rsta * rstb;
return r;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long a1, b1, a2, b2;
cin >> a1 >> b1 >> a2 >> b2;
Rect r1 = decompose(a1, b1);
Rect r2 = decompose(a2, b2);
if (r1.rest != r2.rest) {
cout << -1 << "\n";
return 0;
}
int ops = 0;
// 先平衡 3:將多的 3 轉為 2
if (r1.c3 > r2.c3) {
int d = r1.c3 - r2.c3;
ops += d;
r1.c3 -= d; r1.c2 += d;
} else if (r2.c3 > r1.c3) {
int d = r2.c3 - r1.c3;
ops += d;
r2.c3 -= d; r2.c2 += d;
}
// 再平衡 2:直接減少多的 2
ops += abs(r1.c2 - r2.c2);
// 實際修改邊長
auto apply_ops = [&](Rect& r, int need_reduce_3, int need_reduce_2) {
// need_reduce_3: 需要執行多少次 ÷3×2
// need_reduce_2: 需要執行多少次 ÷2
while (need_reduce_3 > 0) {
if (r.a % 3 == 0) { r.a = r.a / 3 * 2; need_reduce_3--; }
else if (r.b % 3 == 0) { r.b = r.b / 3 * 2; need_reduce_3--; }
}
while (need_reduce_2 > 0) {
if (r.a % 2 == 0) { r.a /= 2; need_reduce_2--; }
else if (r.b % 2 == 0) { r.b /= 2; need_reduce_2--; }
}
};
int r1_reduce_3 = max(0, r1.c3 - r2.c3);
int r2_reduce_3 = max(0, r2.c3 - r1.c3);
int r1_reduce_2 = max(0, r1.c2 - r2.c2);
int r2_reduce_2 = max(0, r2.c2 - r1.c2);
apply_ops(r1, r1_reduce_3, r1_reduce_2);
apply_ops(r2, r2_reduce_3, r2_reduce_2);
cout << ops << "\n";
cout << r1.a << " " << r1.b << "\n";
cout << r2.a << " " << r2.b << "\n";
return 0;
}
此題展示了將操作問題轉化為質因子計數問題的經典數論建模技巧,化繁為簡。