# 演算法課程題解 - 基礎數論 1
# TOJ 292
## 題目
https://toj.tfcis.org/oj/pro/292/
給三個整數 $A, B, C$ ,表示 $C$ 當前為 $A$ 進位制,求轉換成 $B$ 進位制的樣子。其中,我們只會在 $2$~$10$ 進位制之間轉換
## 解法 By Koios1143
### 想法
1. 先將 $C$ 想辦法換成我們熟悉的數字表示方式十進位
2. 統一從十進位轉換為其他進位制
而我們可以透過進位制本身的定義去想,例如 $216 = 2*10^2 + 1*10^1 + 6*10^0$。那麼,我們就可以將任意進位制的數值轉換成我們熟悉的樣子了。
要從十進位轉換成其他進位制,可以直接模擬短除法來達成。例如要將 $15_{10}$ 轉成二進位表示。
$15/2 = 7 ... 1$
$\ \ 7/2 = 3 ... 1$
$\ \ 3/2 = 1 ... 1$
那麼我們可以獲得 $1111_{2}$
### 程式碼
```cpp=
//By Koios1143
#include<iostream>
#include<cmath>
using namespace std;
int N_to_dec(int n, int num){
int ans=0;
for(int i=0 ; num ; i++, num/=10){
ans+=(num%10)*pow(n,i);
}
return ans;
}
string dec_to_M(int m, int num){
string ans="";
for( ; num ; num/=m){
ans = char(num%m + '0') + ans;
}
return ans;
}
int main(){
int A,B,C;
cin>>A>>B>>C;
if(C==0)
cout<<"0\n";
else
cout<<dec_to_M(B,N_to_dec(A,C))<<"\n";
return 0;
}
```
### 複雜度分析
先轉換成十進位的時間複雜度為 $O(log_{10}{n})$
轉換成其他進位的時間複雜度為 $O(log_{10}{n})$
總時間複雜度約為 $O(log_{10}{n})$
# UVa 389
http://domen111.github.io/UVa-Easy-Viewer/?389
給一個字串 $S$ 以及兩個數字 $n, m$ ,表示 $S$ 是 $n$ 進位底下的表示方式,求轉成 $m$ 進位制的樣子。
## 解法 By Koios1143
### 想法
1. 先將 $S$ 想辦法換成我們熟悉的數字表示方式十進位
2. 統一從十進位轉換為其他進位制
做法與上一題是相同的,只是需要處理英文字母的部分
對於每個要轉換過去的單位數字 $p$
1. $p<10$
轉換後為 `char('0'+p)`
2. $p>=10$
轉換後為 `char('A'+p-10)`
### 程式碼
```cpp=
//By Koios1143
#include<iostream>
#include<cmath>
using namespace std;
int main(){
string s;
int n,m,res=0;
while(cin>>s>>n>>m){
res=0;
for(int i=s.size()-1, j=0 ; i>=0 ; i--, j++){
if(s[i]<='9'){
res += (s[i]-'0')*pow(n,j);
}
else{
res += (s[i]-'A'+10)*pow(n,j);
}
}
string ans="";
if(res==0){
ans=" 0";
}
else{
for( ; res && ans.size()<=7 ; res/=m){
int tmp=res%m;
if(tmp>=10){
ans = char(tmp-10+'A') + ans;
}
else{
ans = char(tmp+'0') + ans;
}
}
}
if(ans.size() > 7){
ans=" ERROR";
}
else{
for(int i=ans.size() ; i<7 ; i++){
ans=' ' + ans;
}
}
cout<<ans<<"\n";
}
return 0;
}
```
### 複雜度分析
先轉換成十進位的時間複雜度為 $O(log_{10}{n})$
轉換成其他進位的時間複雜度為 $O(log_{10}{n})$
總時間複雜度約為 $O(log_{10}{n})$
# UVa 10473
## 題目
http://domen111.github.io/UVa-Easy-Viewer/?10473
給一個字串 $S$ ,若 $S$ 是以 `0x` 開頭表示為 $16$ 進位,否則為 $10$ 進位
如果輸入 $16$ 進位,則輸出 $10$ 進位
如果輸入 $10$ 進位,則輸出 $16$ 進位
## 解法 By Koios1143
### 想法
1. 先將 $S$ 想辦法換成我們熟悉的數字表示方式十進位
2. 統一從十進位轉換為其他進位制
做法與上一題是相同的
### 程式碼
```cpp=
//By Koios1143
#include<iostream>
#include<cmath>
using namespace std;
int main(){
string s;
while(cin>>s){
if(s[0]=='-'){
break;
}
if(s.size()>2 && s[1] == 'x'){
// hex
long long ans=0;
for(int i=s.size()-1, j=0 ; i>=2 ; i--, j++){
if(s[i]<='9')
ans+=(s[i]-'0')*pow(16, j);
else
ans+=(s[i]-'A'+10)*pow(16, j);
}
cout<<ans<<"\n";
}
else{
// dec
long long num = 0;
for(int i=s.size()-1, j=0 ; i>=0 ; i--, j++){
num += (s[i]-'0')*pow(10, j);
}
string ans="";
for( ; num ; num/=16){
int m = num%16;
if(m>=10){
ans = char(m-10+'A') + ans;
}
else{
ans = char(m+'0') + ans;
}
}
cout<<"0x"<<ans<<"\n";
}
}
return 0;
}
```
### 複雜度分析
每種轉換方式的時間複雜度皆為 $O(log_{10}{n})$
###### tags: `SCIST 演算法 題解`