# Combinatorics# Precomputation# Brute Force

a364 - 2. 神秘的進位問題

🔗 前往 ZeroJudge 原題

題目描述

題目要求將一個十進位數字 N 轉換成神秘國度的進位表示法 abc,其中 a > b > c >= 0,且 N = C(a, 3) + C(b, 2) + C(c, 1),C(m, n) 為二項係數。

解題思路

由於 N 的範圍較小 (0 <= N <= 500),我們可以預先計算所有可能的 abc 組合,並將其對應的 N 值儲存起來。然後,對於每個輸入的 N,我們只需查找預先計算好的結果即可。預計算時,我們按照 a, b, c 的大小進行遍歷,確保找到字典序最小的解。二項係數的計算使用 cc(m, n) 函數,當 m < n 時返回 0。

複雜度分析

  • 時間複雜度: O(a^3),其中 a 是預計算時的最大 a 值 (在本程式碼中為 501)。 預計算部分的時間複雜度是固定的,查詢部分的時間複雜度是 O(1)。
  • 空間複雜度: O(501^2),用於儲存預計算的結果 ans 陣列。

程式碼

#include <iostream>
using namespace std;
int ans[501][3],al=0;
int cc(int m,int n){
	if(m<n)return 0;
	if(n==1)return m;
	else if(n==2)return m*(m-1)/2;
	return m*(m-1)*(m-2)/6;
}
int main(){
	for(int a=2;al<501;++a){
		int t1=cc(a,3);
		for(int b=1;b<a&&al<501;++b){
			int t2=cc(b,2)+t1;
			for(int c=0;c<b&&al<501;++c){
				int tmp=t2+cc(c,1);
				if(tmp<501&&ans[tmp][0]==0){
					++al;
					ans[tmp][0]=a;
					ans[tmp][1]=b;
					ans[tmp][2]=c;
				} 
			}
		}
	}
	int n;
	while(cin >> n){
		int k;
		while(n--){
			cin >> k;
			for(int i=0;i<3;++i){
				cout << ans[k][i];
			} 
			cout << "\n";
		}
	}
}

Discussion