天平兩邊可放砝碼,每個砝碼三種狀態(左/右/不放),對應三進制。最優選擇:1, 3, 9, 27... 即 w_i = 2×sum_{j。
證明:當前能表示 [1, S],加入 2S+1 可擴展到 [1, 3S+1],砝碼數最少。
目標重量 W,從最大砝碼向下貪心:
ull need[105], sum[105];
void init() {
need[1] = 1; sum[1] = 1;
for (int i = 2; i <= 100; i++) {
need[i] = sum[i-1]*2 + 1;
sum[i] = sum[i-1] + need[i];
}
}
void solve(int maxIdx, ull w) {
int flag = 1; // 1 表示正常,0 表示符號翻轉
while (w) {
for (int i = maxIdx; i >= 1; i--) {
if (w <= sum[i] && w > sum[i-1]) {
printf("%llu", need[i]);
if (w > need[i]) { w -= need[i]; putchar(flag?'+':'-'); }
else if (w < need[i]) { w = need[i] - w; putchar(flag?'-':'+'); flag ^= 1; }
else w = 0;
break;
}
}
}
puts("");
}
unsigned long long 防溢出(need[100] ≈ 3^100)