wikioi-天梯-提高一等-高精度普及-3118:高精度練習之除法
阿新 • • 發佈:2019-02-15
題目描述 Description
給出兩個正整數A和B,計算A/B整數部分的值。保證A和B的位數不超過500位。
輸入描述 Input Description
讀入兩個用空格隔開的正整數
輸出描述 Output Description
輸出A/B整數部分的值
樣例輸入 Sample Input
15 4
樣例輸出 Sample Output
3
資料範圍及提示 Data Size & Hint
兩個正整數的位數不超過500位
型別:高精度 難度:2.5
題意:給出兩個整數(500位以內)A,B,求A/B的結果的整數部分
分析:高精度除法,做下來看的話,感覺涉及的內容還比較多,步驟如下:
1、若A小於B,直接返回0,否則進入下一步
2、計算B的0-10倍數,儲存在陣列bt中(此時用到高精度加法)
3、用now記錄A當前被除數運算部分,將now初始化為A.substr(0,B.length()),即A從左開始擷取B長度的子串,若now比B小,則now末尾再加A的下一位
4、將now看成被除數的窗,不斷右移直到A的末尾,模擬除法運算,每次用now和bt[i](1<=i<=10)作比較,直到bt[i]>now,那麼i-1就是當前位的商,加入結果字串c的末尾
5、更新now,now=now-bt[i-1](此處用到高精度減法)然後將被除數窗右移一位,即now末尾加上A串的下一位
注意:
1、若now為0的話,我用空字串記錄,所以第5步窗移的時候要判斷,特殊處理,高精度減法的時候也要特殊處理
2、去掉string型別字串末尾的字元,若用a[a,length()-1] = '\0',那麼a.length()不會改變,必須用a = a.substr(0,a.length()-1),這是一個string的用法小技巧
程式碼:
#include<iostream> #include<string> using namespace std; string rev(string a) { string ret = a; int n = a.length(); for(int i=0; i<n/2; i++) { char tmp = ret[i]; ret[i] = ret[n-i-1]; ret[n-i-1] = tmp; } return ret; } string add(string a,string b) { int la = a.length(); int lb = b.length(); a = rev(a); b = rev(b); int carry = 0; string c; int i; for(i=0; i<la && i<lb; i++) { int ai = a[i]-'0'; int bi = b[i]-'0'; int ci = ai+bi+carry; c += (ci%10)+'0'; carry = ci/10; } for(; i<la; i++) { int ai = a[i]-'0'; int ci = ai+carry; c += (ci%10)+'0'; carry = ci/10; } for(; i<lb; i++) { int bi = b[i]-'0'; int ci = bi+carry; c += (ci%10)+'0'; carry = ci/10; } if(carry) c += '1'; return rev(c); } string sub(string a,string b) { int la = a.length(); int lb = b.length(); if(la<lb || (la==lb && a<b)) return ""; a = rev(a); b = rev(b); int carry = 0; string c; int i; for(i=0; i<la && i<lb; i++) { int ai = a[i]-'0'; int bi = b[i]-'0'; int ci = ai-bi-carry; if(ci<0) { ci += 10; carry = 1; } else carry = 0; c += (ci%10)+'0'; } for(; i<la; i++) { int ai = a[i]-'0'; int ci = ai-carry; if(ci<0) { ci += 10; carry = 1; } else carry = 0; c += (ci%10)+'0'; } int lc = c.length(); for(i=c.length()-1; i>=0; i--) { if(c[i]=='0') lc--; else break; } if(lc==0) return ""; c = c.substr(0,lc); return rev(c); } string divide(string a,string b) { int la = a.length(); int lb = b.length(); if(la<lb || (la==lb && a<b)) return "0"; string bt[11]; bt[0] = ""; bt[1] = b; for(int j=2; j<=10; j++) { bt[j] = add(bt[j-1],bt[1]); //cout<<rev(s[j])<<endl; } int i = lb-1; string c; string now = a.substr(0,lb); if(now<b) { now += a[++i]; } for(; i<la; i++) { int ci; int lnow = now.length(); for(ci=1; ci<=10; ci++) { int lbn = bt[ci].length(); if(lbn>lnow || (lbn==lnow && bt[ci]>now)) break; } ci--; c += ci+'0'; now = sub(now,bt[ci]); if(i<la-1) { if(now.size()==0 && a[i+1]=='0') continue; now += a[i+1]; } } return c; } int main() { string a,b; cin>>a>>b; cout<<divide(a,b)<<endl; }