两大数相加,一大一小相乘,相除,取余,这类的大数相对简单,只需要用字符串细心模拟计算过程即可。
m转n进制:
- 先将m进制转10进制:
- 从低位到高位遍历m进制每一位,乘以相应的权值(m^0, m^1…)加和即可
- 在将10进制转化为n进制:
- 除n取余法
如果加上 大数 , 就先将主体写清楚,具体的加法,乘除,取余,就用大数模拟。
详细的写在代码注释:
#include <bits/stdc++.h>
using namespace std ;
const int AX = 1e6 + 666 ;
char s[AX] ; // 存储要转为n进制的m进制大数
char res[AX] ; // 存储10->n进制的结果
int a[AX] , b[AX] ; // a[]:在m转10进制过程中,存储每次的s[i]*m^base b[]:存储m进制转为10进制的结果
int k , kb , tot ; // k : a[]索引,kb:b[]索引 , tot : res[]索引
int m , n ; // m -> n 进制
void add() { //大数加法:两个大数存于a[],b[],结果覆盖在b[],长度kb(索引起止:1->kb)
int len = max( k , kb );
int c = 0 ;
for( int i = 1 ; i <= len ; i++ ) {
b[i] = b[i] + a[i] + c ;
c = b[i] / 10000 ;
b[i] %= 10000 ;
}
if( c ) b[++len] += c ;
kb = len ;
}
/*大数乘法(一个大数,一个非大数<这里是进制m和m进制每位置的数>相乘),
结果存于a[],长度k,索引起止 1-k*/
void mul( int num , int x ) {
for( int i = 1 ; i <= num ; i++ ) { //从低位到高位,幂次为num,则乘num次(m^num)
int c = 0 ;
for( int j = 1 ; j <= k ; j++ ) {
a[j] = a[j] * x + c ;
c = a[j] / 10000 ;
a[j] %= 10000 ;
}
if( c ) a[++k] = c ;
}
}
/*大数取余,一个大数存于b[],要转n进制,故对非大数n取余*/
int module() {
int remain = 0 ;
for( int i = kb ; i >= 1 ; i-- ) { //从高位开始除,模拟除法过程
int t = ( remain * 10000 + b[i] ) / n ; //因为从高位,且每个位置存10000,故余数*10000
int r = ( remain * 10000 + b[i] ) % n ;
remain = r ;
}
return remain ;
}
/*大数除法,一个大数存于b[],要转n进制,除以n*/
void div() {
int remain = 0 ;
for( int i = kb ; i >= 1 ; i-- ) {
int t = ( remain * 10000 + b[i] ) / n ;
int r = ( remain * 10000 + b[i] ) % n ;
b[i] = t ;
remain = r ;
}
for( int i = 1 ; i <= kb ; i++ ) { //去除高位0
if( !b[i] ) {
kb = max( 0 , i - 1 ) ;
break ;
}
}
}
void ten_to_n() { // 10进制b[]转n进制的除n取余法主体,结果存于res[],长度tot,索引起止[0,tot).
tot = 0 ;
while(1) {
int r = module() ; //b[]对n取余,结果存于r
if( r >= 10 ) res[tot++] = r - 10 + 'A';
else res[tot++] = r + '0' ;
div(); //对b[]做除法
if( !b[kb] ) break ; //被除数为0,跳出循环
}
}
void m_to_ten( int len ) { //m进制转10进制
int base = 0 ; //每位对应的权,如2转10进制,第一位2^0 ,第二位2^1...
kb = 1 ;
memset( b , 0 ,sizeof(b) );
for( int i = len - 1 ; i >= 0 ; i-- ) {
k = 1 ;
a[1] = 1 ;
int x ;
mul(base,m) ;//得到每一位处要乘的权值
if( s[i] >= '0' && s[i] <= '9' ) x = (int)(s[i]-'0'); //处理10进制以上的符号表示
else {
if( s[i] >= 'a' && s[i] <= 'z' ) s[i] = s[i] - 'a' + 'A' ;
x = ( 10 + (int)(s[i]-'A') ) ;
}
mul(1,x); //将每一位x与权相乘
add(); //加和每次的x*m^base,得到b[],即10进制形式
base ++ ;
}
ten_to_n(); //m进制转十进制成功,存于b[],开始用10进制转n进制
}
int main() {
scanf("%d",&m);
scanf("%s",s);
scanf("%d",&n);
int len = strlen(s);
m_to_ten(len);
/*
print the result of m_to_len : verified 测试转10进制结果
int f = 0 ;
for( int i = kb ; i >= 1; i-- ) {
if( i == k && !b[i] ) continue ;
if( f ) printf("%04d",b[i]);
else {
printf("%d",b[i]);
f = 1 ;
}
}
printf("\n");
*/
for( int i = tot - 1 ; i >= 0 ; i-- ) { //最终10进制转n进制的结果
printf("%c",res[i]);
}
printf("\n");
return 0 ;
}