1. 程式人生 > >wikioi-天梯-提高一等-高精度普及-3118:高精度練習之除法

wikioi-天梯-提高一等-高精度普及-3118:高精度練習之除法

題目描述 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;
}