1. 程式人生 > >C++實現大數除法

C++實現大數除法

題外話

大數除法無疑是大數操作裡最麻煩的一項,寫大數不實現除法無異於畫龍無鱗。

思路

最原始的,腦子最容易冒出來的思路,是一下一下的減,看能累計減多少次,最後的總次數就是結果,但這樣的效率實在太慢。但我們可以一次性減去 除數的1,10,100,1000倍,只要它在當前倍數下比被除數小。
例如 1210 3 ,121大於300,我們直接剪去300,給結果加100,這樣的話,減的次數會大大減小。
基本的思想就是這樣,具體細節見程式碼,這裡不再贅述

進一步優化的方案

上文所述,時間複雜度最壞情況是 9(n-m)*m (解的最壞位數為n-m位,每一位的解最多要減9次,每剪一次需要O(m))
當n,m為萬級時,效率仍不盡人意。看大牛程式碼,發現有這樣一個優化的方案。
我們正常用陣列來表式大數時,是按照10進位制來儲存的,我們可以用比如10000來儲存,那麼長度為n的大數,長度就變為n/4
時間複雜度為原來的1/8

程式碼(未優化)

#include <stdio.h>
#include <iostream>
#include <vector>
#include <math.h>
#include <algorithm>
#include <queue>
#include <string.h>
#include <set>
#include <stack>
#include <stdlib.h>
#include <time.h>

using namespace std
; const int N = 100009; struct Node { int d[N]; int len; Node() {memset(d, 0, sizeof(d));len=1;} Node(char *s) { memset(d, 0, sizeof(d)); len = strlen(s); int i = 0; while(s[i] != '\0') { d[len-i-1] = s[i] - '0'; ++i; } } int
cmp(const Node &t) { int l = this->len - t.len; if(l < 0) return -1; int i; for(i=t.len-1;i>=0;i--) { if(this->d[i+l] < t.d[i]) break; else if(this->d[i+l] > t.d[i]) { return l; } } if(i < 0) return l; return l-1; } void change(int pos) { this->d[pos] += 1; int i = pos; while(this->d[i] > 9) { this->d[i] -= 10; this->d[i+1]++; ++i; } if(i+1 > this->len) this->len = i+1; } Node operator / (const Node &t) { Node ans; while(1) { int p = this->cmp(t); if(p == -1) break; else { ans.change(p); for(int i=0;i<t.len;i++) { this->d[i+p+1]--; this->d[i+p] = this->d[i+p]+10-t.d[i]; if(this->d[i+p] > 9) { this->d[i+p] -= 10; this->d[i+1+p]++; } } while(this->len > 1 && this->d[this->len - 1] == 0) this->len--; } } return ans; } }; char str[N]; int main() { scanf("%s",str); Node a(str); scanf("%s",str); Node b(str); Node ans = a / b; for(int i=ans.len-1;i>=0;i--)//商 printf("%d",ans.d[i]); printf("\n"); for(int i=a.len-1;i>=0;i--)//模 printf("%d",a.d[i]); printf("\n"); return 0; }