大數加(2大數) 乘 除 取餘(一大數) + 大數m進制轉n進制

兩大數相加,一大一小相乘,相除,取餘,這類的大數相對簡單,只需要用字符串細心模擬計算過程即可。

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 ;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章