高精度除法

传送门
思路

正解太神仙,我不会。然而考试的时候我连高精度除法都没有写,只因为没有写过……

参考代码
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <cassert>
#include <cctype>
#include <climits>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <list>
#include <functional>
using LL = long long;
using ULL = unsigned long long;
using std::cin;
using std::cout;
using std::endl;
using INT_PUT = int;
INT_PUT readIn()
{
    INT_PUT a = 0;
    bool positive = true;
    char ch = getchar();
    while (!(std::isdigit(ch) || ch == '-')) ch = getchar();
    if (ch == '-')
    {
        positive = false;
        ch = getchar();
    }
    while (std::isdigit(ch))
    {
        (a *= 10) -= ch - '0';
        ch = getchar();
    }
    return positive ? -a : a;
}
void printOut(INT_PUT x)
{
    char buffer[20];
    int length = 0;
    if (x < 0) putchar('-');
    else x = -x;
    do buffer[length++] = -(x % 10) + '0'; while (x /= 10);
    do putchar(buffer[--length]); while (length);
    putchar('\n');
}

const int mod = int(1e9) + 7;
const int maxn = int(1e6) + 5;
const int maxm = int(1e5) + 5;
int n, m;
int val[maxn];
struct Ins
{
    int type;
    int x, a;
    void read()
    {
        char buffer[5];
        scanf("%s", buffer);
        type = (buffer[0] == 'Q') + 1;
        x = readIn();
        a = readIn();
    }
} inss[maxm];

#define RunInstance(x) delete new x
struct brute
{
    static const int maxN = 10005;
    int dividend[maxN];
    int divisor[maxN];
    int quotient[maxN];
    void Div()
    {
        dividend[dividend[0] + 1] = 0;
        quotient[0] = dividend[0] - divisor[0] + 1;
        for (int i = dividend[0]; i >= divisor[0]; i--)
        {
            int& ans = quotient[i - divisor[0] + 1];
            ans = 0;
            while (ans < 9)
            {
                for (int j = 1; j <= divisor[0]; j++)
                    dividend[i - divisor[0] + j] -= divisor[j];
                for (int j = 1; j <= divisor[0]; j++)
                    if (dividend[i - divisor[0] + j] < 0)
                    {
                        dividend[i - divisor[0] + j] += 10;
                        dividend[i - divisor[0] + j + 1]--;
                    }
                if (dividend[i + 1] < 0)
                {
                    for (int j = 1; j <= divisor[0]; j++)
                    {
                        dividend[i - divisor[0] + j] += divisor[j];
                        if (dividend[i - divisor[0] + j] >= 10)
                        {
                            dividend[i - divisor[0] + j] -= 10;
                            dividend[i - divisor[0] + j + 1]++;
                        }
                    }
                    break;
                }
                ans++;
            }
        }
        while (quotient[0] > 1 && !quotient[quotient[0]])
            quotient[0]--;
        while (dividend[0] > 1 && !dividend[dividend[0]])
            dividend[0]--;
    }

    brute()
    {
        for (int i = 1; i <= m; i++)
        {
            const Ins& ins = inss[i];
            if (ins.type == 1)
            {
                val[ins.x] = ins.a;
            }
            else
            {
                if (ins.x > n)
                {
                    LL ans = 0;
                    for (int i = 1; i <= n; i++)
                        ((ans *= 10) += val[i]) %= mod;
                    printOut(ans);
                }
                else
                {
                    dividend[0] = n;
                    for (int i = n; i; i--)
                        dividend[n - i + 1] = val[i];
                    divisor[0] = ins.x;
                    for (int i = 1; i <= ins.x; i++)
                        divisor[i] = ins.a;
                    Div();
                    LL ans = 0;
                    for (int i = dividend[0]; i; i--)
                        ((ans *= 10) += dividend[i]) %= mod;
                    printOut(ans);
                }
            }
        }
    }
};

void run()
{
    n = readIn();
    for (int i = 1; i <= n; i++)
    {
        char ch = getchar();
        while (!std::isdigit(ch))
            ch = getchar();
        val[i] = ch - '0';
    }
    m = readIn();
    for (int i = 1; i <= m; i++)
        inss[i].read();

    if (n <= 10000)
        RunInstance(brute);
}

int main()
{
    run();
    return 0;
}

Div 函数就是高精度除以高精度了。除完后被除数变成了余数,商放在 quotient 里。

注意事项
  1. 高精度除法的策略是从高位向低位一直做减法来模拟试商的过程,如果相减后发现出现了负数,就还原,并且退出当前位的计算。
  2. 时间复杂度为 O ( n 2 )
  3. 不必手动将余数保留到下一位,因为会借位。记住将被除数的最高位的上一位清零,以正确处理最高位的借位。
  4. 商的位数(包含前导零)等于被除数的位数减去除数的位数加一。
  5. 去除前导零时一定要保留一位,否则当答案为 0 时将输出空白。
  6. 注意差一错误(然而并不是很难)。

猜你喜欢

转载自blog.csdn.net/lycheng1215/article/details/80820896