在一個神秘的國家,他們有不同的文明,他們所使用的數字表示法跟常見的 十進位法不一樣。對於一個十進位的數字 N,他們會表示成 abc,其中 a > b > c >= 0 ,且滿足 N= C(a, 3) + C(b, 2) + C(c, 1) , C 為二項係數,即 C(m, n) = m!/(n!(m-n)!),但當 m < n 時,C(m, n) = 0。為幫助了解這個神秘國度的文化, 請寫一程式來將十進位數轉換成這個神秘的進位法。
範例測資
範例輸入 | 範例輸出 |
---|---|
第一行有一個整數 m,1 ≤ m ≤ 10,代表要轉換的十進位數的個數。接下來的 m 行(第 2 行至第 (m+1) 行):每一行都有一個介於 0 和 500 之間的整數,代表要轉換的十進位數。 | 針對每一個十進位數分別在一行輸出對應的 abc,其間不需留空白,注意 a、 b 和 c 未必是只有一位數,若答案不唯一時請輸出字典順序最小的表示法,即盡 可能取小的 a 及 b 值。 |
4 0 1 2 200 | 210 310 320 1187 |
3 18 19 20 | 542 543 610 |
解題思路
可以使用 DFS 來跑所有可能,包括只增加其中一個數字或是兩個數字或是全部都加,但是需要確保 a > b > c,所以一開始在呼叫 DFS 時,a = 2、b = 1、c = 0。
範例程式碼-ZeroJudge A364: 神秘的進位問題
#include <iostream>
using namespace std;
bool ok = false;
int calc (const int a, const int b) {
if (a < b) return 0;
int result = 1, divisor = 1;;
for (int i = 0; i<b; i++) {
result *= a-i;
divisor *= i+1;
}
return result/divisor;
}
int cCalc(const int A, const int B, const int C) {
return calc(A, 3) + calc(B, 2) + calc(C, 1);
}
void DFS(const int A, const int B, const int C, const int target) {
if (ok) return;
const int result = cCalc(A, B, C);
if (result > target) return;
if (result == target) {
cout << A << B << C << endl;
ok = true;
return;
}
if (A+1 > B && B > C) DFS(A+1, B, C, target);
if (A > B+1 && B+1 > C) DFS(A, B+1, C, target);
if (A > B && B > C+1) DFS(A, B, C+1, target);
if (A+1 > B+1 && B+1 > C) DFS(A+1, B+1, C, target);
if (A > B+1 && B+1 > C+1) DFS(A, B+1, C+1, target);
if (A+1 > B && B > C+1) DFS(A+1, B, C+1, target);
DFS(A+1, B+1, C+1, target);
}
int main() {
cin.sync_with_stdio(0);
cin.tie(0);
int M;
cin >> M;
for (int i = 0; i < M; i++) {
int N;
cin >> N;
ok = false;
DFS(2, 1, 0, N);
}
}
//ZeroJudge A364
//Dr. SeanXD