ACM模版

普通大数运算

const int MAXSIZE = 200;

void Add(char *str1, char *str2, char *str3);
void Minus(char *str1, char *str2, char *str3);
void Mul(char *str1, char *str2, char *str3);
void Div(char *str1, char *str2, char *str3);

int main()
{
    char str1[MAXSIZE], str2[MAXSIZE], str3[MAXSIZE];
    while (scanf("%s %s", str1, str2) == 2)
    {
        if (strcmp(str1, "0"))
        {
            memset(str3, '0', sizeof(str3));
            Add(str1, str2, str3);
            printf("%s\n", str3);
            memset(str3, '0', sizeof(str3));
            Minus(str1, str2, str3);
            printf("%s\n", str3);
            memset(str3, '0', sizeof(str3));
            Mul(str1, str2, str3);
            printf("%s\n", str3);
            memset(str3, '0', sizeof(str3));
            Div(str1, str2, str3);
            printf("%s\n", str3);
        }
        else
        {
            if (strcmp(str2, "0"))
            {
                printf("%s\n-%s\n0\n0\n", str2, str2);
            }
            else
            {
                printf("0\n0\n0\n0\n");
            }
        }
    }
    return 0;
}

void Add(char *str1, char *str2, char *str3)
{   // str3 = str1 + str2;
    int i, j, i1, i2, tmp, carry;
    int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
    char ch;
    i1 = len1 - 1;
    i2 = len2 - 1;
    j = carry = 0;
    for (; i1 >= 0 && i2 >= 0; ++j, --i1, --i2)
    {
        tmp = str1[i1] - '0' + str2[i2] - '0' + carry;
        carry = tmp / 10;
        str3[j] = tmp % 10 + '0';
    }
    while (i1 >= 0)
    {
        tmp = str1[i1--] - '0' + carry;
        carry = tmp / 10;
        str3[j++] = tmp % 10 + '0';
    }
    while (i2 >= 0)
    {
        tmp = str2[i2--] - '0' + carry;
        carry = tmp / 10;
        str3[j++] = tmp % 10 + '0';
    }
    if (carry)
    {
        str3[j++] = carry + '0';
    }
    str3[j] = '\0';
    for (i = 0, --j; i < j; ++i, --j)
    {
        ch = str3[i];
        str3[i] = str3[j];
        str3[j] = ch;
    }
    return ;
}

void Minus(char *str1, char *str2, char *str3)
{   // str3 = str1-str2 (str1 > str2)
    int i, j, i1, i2, tmp, carry;
    int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
    char ch;
    i1 = len1 - 1;
    i2 = len2 - 1;
    j = carry = 0;
    while (i2 >= 0)
    {
        tmp = str1[i1] - str2[i2] - carry;
        if (tmp < 0)
        {
            str3[j] = tmp + 10 + '0';
            carry = 1;
        }
        else
        {
            str3[j] = tmp + '0';
            carry = 0;
        }
        i1--;
        i2--;
        j++;
    }
    while (i1 >= 0)
    {
        tmp = str1[i1] - '0' - carry;
        if (tmp < 0)
        {
            str3[j] = tmp + 10 + '0';
            carry = 1;
        }
        else
        {
            str3[j] = tmp + '0';
            carry = 0;
        }
        --i1;
        ++j;
    }
    --j;
    while (str3[j] == '0' && j > 0)
    {
        --j;
    }
    str3[++j] = '\0';
    for (i = 0, --j; i < j; ++i, --j)
    {
        ch = str3[i];
        str3[i] = str3[j];
        str3[j] = ch;
    }
    return ;
}

void Mul(char *str1, char *str2, char *str3)
{
    int i, j = 0, i1, i2, tmp, carry, jj;
    int len1 = (int)strlen(str1), len2 = (int)strlen(str2);
    char ch;
    jj = carry = 0;
    for (i1 = len1 - 1; i1 >= 0; --i1)
    {
        j = jj;
        for (i2 = len2 - 1; i2 >= 0; --i2, ++j)
        {
            tmp = (str3[j] - '0') + (str1[i1] - '0') * (str2[i2] - '0') + carry;
            if (tmp > 9)
            {
                carry = tmp / 10;
                str3[j] = tmp % 10 + '0';
            }
            else
            {
                str3[j] = tmp + '0';
                carry = 0;
            }
        }
        if (carry)
        {
            str3[j] = carry + '0';
            carry = 0;
            j++;
        }
        jj++;
    }
    j--;
    while (str3[j] == '0' && j > 0)
    {
        j--;
    }
    str3[++j] = '\0';
    for (i = 0, --j; i < j; ++i, --j)
    {
        ch = str3[i];
        str3[i] = str3[j];
        str3[j] = ch;
    }
    return ;
}

void Div(char *str1, char *str2, char *str3)
{
    int i1, i2, i, j, jj = 0, tag, carry, cf, c[MAXSIZE];
    int len1 = (int)strlen(str1), len2 = (int)strlen(str2), lend;
    char d[MAXSIZE];
    memset(c, 0, sizeof(c));
    memcpy(d, str1, len2);
    lend = len2;
    j = 0;
    for (i1 = len2 - 1; i1 < len1; ++i1)
    {
        if (lend < len2)
        {
            d[lend] = str1[i1+1];
            c[j] = 0;
            ++j;
            ++lend;
        }
        else if (lend == len2)
        {
            jj = 1;
            for (i = 0; i < lend; ++i)
            {
                if (d[i] > str2[i])
                {
                    break;
                }
                else if (d[i] < str2[i])
                {
                    jj = 0;
                    break;
                }
            }
            if (jj == 0)
            {
                d[lend] = str1[i1+1];
                c[j] = 0;
                ++j;
                ++lend;
                continue;
            }
        }
        if (jj == 1 || lend > len2)
        {
            cf = jj = 0;
            while (d[jj] <= '0' && jj < lend)
            {
                ++jj;
            }
            if (lend - jj > len2)
            {
                cf = 1;
            }
            else if (lend - jj < len2)
            {
                cf = 0;
            }
            else
            {
                i2 = 0;
                cf = 1;
                for (i = jj; i < lend; ++i)
                {
                    if (d[i] < str2[i2])
                    {
                        cf = 0;
                        break;
                    }
                    else if (d[i] > str2[i2])
                    {
                        break;
                    }
                    ++i2;
                }
            }
            while (cf)
            {
                i2 = len2 - 1;
                cf = 0;
                for (i = lend - 1; i >= lend - len2; --i)
                {
                    d[i] = d[i] - str2[i2] + '0';
                    if (d[i] < '0')
                    {
                        d[i] = d[i] + 10;
                        carry = 1;
                        --d[i - 1];
                    }
                    else
                    {
                        carry = 0;
                    }
                    --i2;
                }
                ++c[j];
                jj = 0;
                while (d[jj] <= '0' && jj < lend)
                {
                    ++jj;
                }
                if (lend - jj > len2)
                {
                    cf = 1;
                }
                else if (lend - jj < len2)
                {
                    cf = 0;
                }
                else
                {
                    i2 = 0;
                    cf = 1;
                    for (i = jj; i < lend; ++i)
                    {
                        if (d[i] < str2[i2])
                        {
                            cf = 0;
                            break;
                        }
                        else if (d[i] > str2[i2])
                        {
                            break;
                        }
                        ++i2;
                    }
                }
            }
            jj = 0;
            while (d[jj] <= '0' && jj < lend)
            {
                ++jj;
            }
            for (i = 0; i < lend - jj; ++i)
            {
                d[i] = d[i + jj];
            }
            d[i] = str1[i1 + 1];
            lend = i + 1;
            j++;
        }
    }
    i = tag = 0;
    while (c[i] == 0)
    {
        ++i;
    }
    for (; i < j; ++i, ++tag)
    {
        str3[tag] = c[i]+'0';
    }
    str3[tag] = '\0';
    return ;
}

高效大数运算

/* * < , <= , + , - , * , / , %(修改/的最后一行可得) */
const int base = 10000;     // (base^2) fit into int
const int width = 4;        // width = log_10(base)
const int MAXN = 100000;    // MAXN * width: 可表示的最大位数
const int MAXC = 1e5 + 10;

struct bint
{
    int ln, v[MAXN];

    bint (int r = 0)
    {
        // r应该是字符串!
        for (ln = 0; r > 0; r /= base)
        {
            v[ln++] = r % base;
        }
    }

    bint &operator = (const bint &r)
    {
        memcpy(this, &r, (r.ln + 1) * sizeof(int));
        return *this;
    }
};

bool operator < (const bint &a, const bint &b)
{
    int i;
    if (a.ln != b.ln)
    {
        return a.ln < b.ln;
    }
    for (i = a.ln - 1; i >= 0 && a.v[i] == b.v[i]; i--) ;

    return i < 0 ? 0 : a.v[i] < b.v[i];
}

bool operator <= (const bint &a, const bint &b)
{
    return !(b < a);
}

bint operator + (const bint &a, const bint &b)
{
    bint res;
    int i, cy = 0;
    for (i = 0; i < a.ln || i < b.ln || cy > 0; i++)
    {
        if (i < a.ln)
        {
            cy += a.v[i];
        }
        if (i < b.ln)
        {
            cy += b.v[i];
        }
        res.v[i] = cy % base;
        cy /= base;
    }
    res.ln = i;

    return res;
}

bint operator - (const bint &a, const bint &b)
{
    bint res;
    int i, cy = 0;
    for (res.ln = a.ln, i = 0; i < res.ln; i++)
    {
        res.v[i] = a.v[i] - cy;
        if (i < b.ln)
        {
            res.v[i] -= b.v[i];
        }
        if (res.v[i] < 0)
        {
            cy = 1, res.v[i] += base;
        }
        else
        {
            cy = 0;
        }
    }
    while (res.ln > 0 && res.v[res.ln - 1] == 0)
    {
        res.ln--;
    }

    return res;
}

bint operator * (const bint &a, const bint &b)
{
    bint res;
    res.ln = 0;
    if (0 == b.ln)
    {
        res.v[0] = 0;
        return res;
    }
    int i, j, cy;
    for (i = 0; i < a.ln; i++)
    {
        for (j = cy = 0; j < b.ln || cy > 0; j++, cy /= base)
        {
            if (j < b.ln)
            {
                cy += a.v[i] * b.v[j];
            }
            if (i + j < res.ln)
            {
                cy += res.v[i + j];
            }
            if (i + j >= res.ln)
            {
                res.v[res.ln++] = cy % base;
            }
            else
            {
                res.v[i + j] = cy % base;
            }
        }
    }

    return res;
}

bint operator / (const bint &a, const bint &b)
{   // !b != 0
    bint tmp, mod, res;
    int i, lf, rg, mid;
    mod.v[0] = mod.ln = 0;
    for (i = a.ln - 1; i >= 0; i--)
    {
        mod = mod * base + a.v[i];
        for (lf = 0, rg = base -1; lf < rg;)
        {
            mid = (lf + rg + 1) / 2;
            if (b * mid <= mod)
            {
                lf = mid;
            }
            else
            {
                rg = mid - 1;
            }
        }
        res.v[i] = lf;
        mod = mod - b * lf;
    }
    res.ln = a.ln;
    while (res.ln > 0 && res.v[res.ln - 1] == 0)
    {
        res.ln--;
    }

    return res;     // return mod; 就是%运算
}

int digits(bint& a) // 返回位数
{
    if (a.ln == 0)
    {
        return 0;
    }
    int l = (a.ln - 1) * 4;
    for (int t = a.v[a.ln - 1]; t; ++l, t /= 10);

    return l;
}

bool read(bint &b, char buf[])  // 读取失败返回0
{
    if (1 != scanf("%s", buf))
    {
        return 0;
    }
    int w, u, ln = (int)strlen(buf);
    memset(&b, 0, sizeof(bint));
    if ('0' == buf[0] && 0 == buf[1])
    {
        return 1;
    }
    for (w = 1, u = 0; ln; )
    {
        u += (buf[--ln] - '0') * w;
        if (w * 10 == base)
        {
            b.v[b.ln++] = u;
            w = 1;
            u = 0;
        }
        else
        {
            w *= 10;
        }
    }
    if (w != 1)
    {
        b.v[b.ln++] = u;
    }

    return 1;
}

void write(const bint &v)
{
    int i;
    printf("%d", v.ln == 0 ? 0 : v.v[v.ln - 1]);
    for (i = v.ln - 2; i >= 0; i--)
    {
        printf("%04d", v.v[i]); // !!! 4 == width
    }
    printf("\n");

    return ;
}

char buf[MAXC];

int main()
{
    bint A, B, C, D;
    read(A, buf);
    read(B, buf);
    C = A / B;  // floor(A/B)
    write(C);

    D = B * C;
    D = A - D;  // A%B
    write(D);

    return 0;
}

2017.8.6 修改 高效大数运算 代码

加强版大数运算

typedef long long ll;

class BigInteger
{
private:
    const static int MOD = (119 << 23) + 1;
    const static int root = 3;
    const static int invroot = 332748118;

    int *a;
    int length, sig;

    void apply(int length)
    {
        if (!length)
        {
            return ;
        }
        a = new int [length]();
        this -> length = length;
    }

    void destroy()
    {
        if (!length)
        {
            return ;
        }
        delete [] a;
        a = nullptr;
    }

    void resize(int length)
    {
        if (length == this->length)
        {
            return ;
        }
        if (!length)
        {
            return destroy();
        }
        int *aux = a;
        a = new int [length]();
        memcpy(a, aux, sizeof(int) * min(length, this->length));
        if (this->length)
        {
            delete [] aux;
        }
        this->length = length;
    }

    BigInteger(int length) : length(length), sig(0)
    {
        apply(length);
    }

    BigInteger(const BigInteger &p, int length) : length(length), sig(p.sig)
    {
        apply(length);
        memcpy(a, p.a, sizeof(int) * min(p.length, length));
    }

    bool absgreaterequal(const BigInteger &q) const &
    {
        if (length != q.length)
        {
            return length > q.length;
        }
        for (int i = length - 1; ~i; -- i)
        {
            if (a[i] > q.a[i])
            {
                return true;
            }
            if (a[i] < q.a[i])
            {
                return false;
            }
        }
        return true;
    }

    BigInteger operator << (const int &dis) const &
    {
        if (!sig)
        {
            return *this;
        }
        BigInteger ret(length + dis);
        memcpy(ret.a + dis, a, sizeof(int) * length);
        ret.sig = sig;

        return ret;
    }

    BigInteger operator >> (const int &dis) const &
    {
        if (dis >= length)
        {
            return BigInteger();
        }
        BigInteger ret(length - dis);
        memcpy(ret.a, a + dis, sizeof(int) * ret.length);
        ret.sig = sig;
        return ret;
    }

    int powermod(int a, int exp) const &
    {
        int ret = 1;
        for (; exp; exp >>= 1)
        {
            if (exp & 1)
            {
                ret = (ll) ret * a % MOD;
            }
            a = (ll) a * a % MOD;
        }
        return ret;
    }

    void NTT(int *a, int length, int type) const &
    {
        int len = -1;
        for (int x = length; x; ++len, x >>= 1) ;
        for (int i = 1, j = 0; i < length - 1; ++i)
        {
            for (int s = length; j ^= s >>= 1, ~j & s; ) ;
            if (i < j)
            {
                swap(a[i], a[j]);
            }
        }
        for (int i = 1; i <= len; ++ i)
        {
            for (int j = 0, unit = powermod(type == 1 ? root : invroot, (MOD - 1) >> i), szk = 1 << (i - 1); j < length; j += 1 << i)
            {
                for (int k = j, w = 1; k < j + szk; ++ k)
                {
                    int s = a[k], t = (ll) w * a[k + szk] % MOD;
                    a[k] = s + t >= MOD ? s + t - MOD : s + t;
                    a[k + szk] = s - t < 0 ? s - t + MOD : s - t;
                    w = (ll) w * unit % MOD;
                }
            }
        }
        if (type == 1)
        {
            return ;
        }
        int inv = powermod(length, MOD - 2);
        for (int i = 0; i < length; ++i)
        {
            a[i] = (ll) a[i] * inv % MOD;
        }
    }

    int divide(BigInteger &p, const int &q) const &
    {
        if (!q)
        {
            assert(-1);
        }
        if (!p.sig)
        {
            return 0;
        }
        ll remain = 0, x = abs(q);
        for (int i = length - 1; ~i; -- i)
        {
            remain = remain * 10 + p.a[i];
            p.a[i] = (int)(remain / x);
            remain %= x;
        }
        for (; p.length && !p.a[p.length - 1]; -- p.length) ;
        remain *= p.sig;
        p.sig *= q < 0 ? -1 : 1;
        if (!p.length)
        {
            p.sig = 0;
        }
        return (int)remain;
    }

public:
    BigInteger() : length(0), sig(0) { a = nullptr; }
    BigInteger(const BigInteger &p) : length(p.length), sig(p.sig)
    {
        apply(length), memcpy(a, p.a, sizeof(int) * length);
    }
    ~BigInteger() { destroy(); }
    int getlength() { return length; }
    bool positive() { return sig > 0; }
    bool iszero() { return !sig; }
    bool negative() { return sig < 0; }
    bool even() { return !sig || !(a[0] & 1); }

    BigInteger &operator = (const BigInteger &p)
    {
        destroy();
        apply(p.length);
        length = p.length;
        sig = p.sig;
        memcpy(a, p.a, sizeof(int) * length);
        return *this;
    }

    template <typename T>
    BigInteger &operator = (const T &p)
    {
        destroy();
        sig = p ? p > 0 ? 1 : -1 : 0;
        apply(40);
        int cnt = 0;
        for (T x = abs(p); x; x /= 10)
        {
            a[cnt++] = x % 10;
        }
        resize(cnt);
        return *this;
    }

    void read()
    {
        destroy();
        sig = 1;
        char ch = getchar();
        for ( ; ch < '0' || ch > '9'; ch = getchar())
        {
            if (ch == '-')
            {
                sig = -1;
            }
        }
        resize(1);
        int nowlength = 0;
        for (; ch >= '0' && ch <= '9'; ch = getchar())
        {
            a[nowlength++] = ch - '0';
            if (nowlength == length)
            {
                resize(length << 1);
            }
        }
        reverse(a, a + nowlength);
        for (; nowlength && !a[nowlength - 1]; --nowlength) ;
        resize(nowlength);
        sig = length ? sig : 0;
    }

    void write()
    {
        if (!sig)
        {
            return (void)putchar('0');
        }
        if (sig < 0)
        {
            putchar('-');
        }
        for (int i = length - 1; ~i; i--)
        {
            putchar(a[i] + '0');
        }
    }

    template <typename T>
    T tointeger()
    {
        T ret = 0;
        for (int i = length - 1; i >= 0; ++ i)
        {
            ret = ret * 10 + a[i];
        }
        return ret * sig;
    }

    bool operator == (const BigInteger &p) const &
    {
        if (sig != p.sig || length != p.length)
        {
            return false;
        }
        for (int i = 0; i < length; ++i)
        {
            if (a[i] != p.a[i])
            {
                return false;
            }
        }
        return true;
    }

    bool operator > (const BigInteger &p) const &
    {
        if (sig != p.sig)
        {
            return sig > p.sig;
        }
        if (length != p.length)
        {
            return length > p.length ^ sig == -1;
        }
        for (int i = length - 1; i >= 0; --i)
        {
            if (a[i] > p.a[i])
            {
                return sig > 0;
            }
            if (a[i] < p.a[i])
            {
                return sig < 0;
            }
        }
        return false;
    }

    BigInteger &operator ++ ()
    {
        resize(length + 1);
        sig >= 0 ? ++a[0] : --a[0];
        for (int i = 0; i < length - 1; ++i)
        {
            if (a[i] < 10 && a[i] >= 0)
            {
                break;
            }
            a[i] >= 10 ? (a[i] -= 10, ++a[i + 1]) : (a[i] += 10, --a[i + 1]);
        }
        for (; length && !a[length - 1]; --length) ;
        resize(length);
        sig = length ? sig >= 0 ? 1 : -1 : 0;
        return *this;
    }

    BigInteger &operator -- ()
    {
        sig = -sig;
        ++*this;
        sig = -sig;
        return *this;
    }

    BigInteger operator ++ (int)
    {
        BigInteger aux(*this);
        ++*this;
        return aux;
    }

    BigInteger operator -- (int)
    {
        BigInteger aux(*this);
        --*this;
        return aux;
    }

    BigInteger operator + (const BigInteger &p) const &
    {
        if (!p.sig)
        {
            return *this;
        }
        if (!sig)
        {
            return p;
        }
        bool type = true, flag = sig > 0;
        const BigInteger *aux = this, *aux1 = &p;
        if (sig != p.sig)
        {
            type = false;
            if (!absgreaterequal(p))
            {
                flag = !flag;
                swap(aux, aux1);
            }
        }
        BigInteger ret(*aux, max(length, p.length) + 1);
        for (int i = 0; i < ret.length - 1; ++i)
        {
            ret.a[i] += i < aux1->length ? type ? aux1->a[i] : -aux1->a[i] : 0;
            ret.a[i] >= 10 ? (ret.a[i] -= 10, ++ret.a[i + 1]) : ret.a[i] < 0 ? (ret.a[i] += 10, --ret.a[i + 1]) : 0;
        }
        for (; ret.length && !ret.a[ret.length - 1]; --ret.length) ;
        ret.resize(ret.length);
        ret.sig = ret.length ? flag ? 1 : -1 : 0;
        return ret;
    }

    BigInteger operator - () const &
    {
        BigInteger ret(*this);
        ret.sig = -ret.sig;
        return ret;
    }

    BigInteger operator - (const BigInteger &p) const & { return *this + (-p); }

    BigInteger operator * (const BigInteger &p) const &
    {
        if (!sig || !p.sig)
        {
            return BigInteger();
        }
        int n = length + p.length;
        int lengthret = 1;
        for (; lengthret < n; lengthret <<= 1) ;
        BigInteger ret(*this, lengthret);
        int *aux = new int [lengthret]();
        memcpy(aux, p.a, sizeof(int) * p.length);
        NTT(ret.a, lengthret, 1);
        NTT(aux, lengthret, 1);
        for (int i = 0; i < lengthret; ++i)
        {
            ret.a[i] = (ll) ret.a[i] * aux[i] % MOD;
        }
        NTT(ret.a, lengthret, -1);
        for (int i = 0; i < n - 1; i++)
        {
            ret.a[i + 1] += ret.a[i] / 10;
            ret.a[i] %= 10;
        }
        for (; n && !ret.a[n - 1]; --n) ;
        ret.resize(n);
        ret.sig = sig * p.sig;
        return ret;
    }

    BigInteger operator * (const int &p) const &
    {
        if (!p || !sig)
        {
            return BigInteger();
        }
        BigInteger ret(*this, length + 10);
        ll x = abs(p), remain = 0;
        for (int i = 0; i < length; ++ i)
        {
            remain += ret.a[i] * x;
            ret.a[i] = remain % 10;
            remain /= 10;
        }
        int nowlength = length;
        for (ret.a[nowlength] = (int)remain; ret.a[nowlength]; ++nowlength)
        {
            ret.a[nowlength + 1] = ret.a[nowlength] / 10;
            ret.a[nowlength] %= 10;
        }
        for (; nowlength && !ret.a[nowlength - 1]; --nowlength) ;
        ret.resize(nowlength);
        ret.sig = sig * (p < 0 ? -1 : 1);
        return ret;
    }

    BigInteger operator / (const BigInteger &p) const &
    {
        if (!p.sig)
        {
            assert(-1);
        }
        if (!sig || length < p.length)
        {
            return BigInteger();
        }
        int num = 0;
        for (int i = p.length - 1; i >= p.length - 3; --i)
        {
            (num *= 10) += i >= 0 ? p.a[i] : 0;
        }
        num = 100000 / num;
        int nowprecision = 1;
        BigInteger ret;
        ret = num;
        for (; nowprecision <= length - p.length; nowprecision <<= 1)
        {
            BigInteger aux((nowprecision << 1) + 3);
            aux.sig = 1;
            for (int i = p.length - aux.length; i < p.length; ++i)
            {
                aux.a[i - p.length + aux.length] = i >= 0 ? p.a[i] : 0;
            }
            aux = (aux * ret >> (nowprecision + 2)) * ret >> (nowprecision + 2);
            ret = (ret * 2 << nowprecision) - aux;
        }
        ret = ret * *this >> (p.length + nowprecision + 1);
        ret.sig = abs(ret.sig);
        BigInteger aux(p);
        aux.sig = abs(aux.sig);
        if (!absgreaterequal(ret * aux))
        {
            --ret;
        }
        else if (!absgreaterequal(++ret * aux))
        {
            --ret;
        }
        ret.sig *= sig * p.sig;
        return ret;
    }

    BigInteger operator / (const int &p) const &
    {
        BigInteger ret(*this);
        divide(ret, p);
        ret.resize(ret.length);
        return ret;
    }

    BigInteger sqrt() const &
    {
        if (sig < 0)
        {
            assert(-1);
        }
        if (!sig)
        {
            return *this;
        }
        int num = 0;
        for (int i = length - 1; i >= length - 8; --i)
        {
            (num *= 10) += i >= 0 ? a[i] : 0;
        }
        ll x = length & 1 ? 10000000000000ll : 100000000000000ll;
        num = std::sqrt(1.0 * x / num); // 命名空间不能省
        int nowprecision = 2;
        BigInteger ret;
        ret = num;
        for (; nowprecision <= (length >> 1) + 1; nowprecision = (nowprecision << 1) - 1)
        {
            BigInteger aux((nowprecision << 1) + 1 + (length & 1));
            aux.sig = 1;
            for (int i = length - aux.length; i < length; ++i)
            {
                aux.a[i - length + aux.length] = i >= 0 ? a[i] : 0;
            }
            aux = ((aux * ret >> (nowprecision + 1)) * ret >> (nowprecision + 1)) / 2;
            BigInteger aux1((nowprecision + 1) << 1);
            aux1.sig = 1;
            aux1.a[aux1.length - 1] = 1, aux1.a[aux1.length - 2] = 5;
            ret = ret * (aux1 - aux) >> (nowprecision + 2);
        }
        ret = ret * *this >> ((length >> 1) + nowprecision + 1);
        if (!absgreaterequal(ret * ret))
        {
            --ret;
        }
        else
        {
            ++ret;
            if (!absgreaterequal(ret * ret))
            {
                --ret;
            }
        }
        return ret;
    }

    BigInteger operator % (const BigInteger &p) const &
    {
        if (!p.sig)
        {
            assert(-1);
        }
        return *this - *this / p * p;
    }

    int operator % (const int &p) const &
    {
        if (!p)
        {
            assert(-1);
        }
        BigInteger aux(*this);
        return divide(aux, p);
    }

    friend BigInteger operator * (const int &q, const BigInteger &p) { return p * q; }
    BigInteger &operator += (const BigInteger &p) { *this = *this + p; return *this; }
    BigInteger &operator -= (const BigInteger &p) { *this = *this - p; return *this; }
    BigInteger &operator *= (const BigInteger &p) { *this = *this * p; return *this; }
    BigInteger &operator *= (const int &p) { *this = *this * p; return *this; }
    BigInteger &operator /= (const BigInteger &p) { *this = *this / p; return *this; }
    BigInteger &operator /= (const int &p) { *this = *this / p; return *this; }
    BigInteger &operator %= (const BigInteger &p) { *this = *this % p; return *this; }
    BigInteger &operator %= (const int &p) { *this = *this % p; return *this; }

    template <typename T> 
    BigInteger power(T exp) const &
    {
        BigInteger ret = 1, aux(*this);
        for (; exp; exp >>= 1)
        {
            if (exp & 1)
            {
                ret *= aux;
            }
            aux *= aux;
        }

        return ret;
    }
};

BigInteger a;

int main()
{
    a.read();
    a.sqrt().write();
    putchar(10);

    return 0;
}

2017.8.6 添加 加强版大数运算
2018.5.11 修改 不只是四则运算,包含开方取模