ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

高精度

2022-08-20 16:31:06  阅读:118  来源: 互联网

标签:return 高精度 ubigint bigint const friend size


高精度

以下均为压位高精度 高精度除高精度以二分法求

以下均含divide带余数除法 TODO:FFT高精度除高精度

快速傅里叶加速乘法

Code
namespace FFT {
using cpx = complex<double>;
const double PI = acos(-1);
vector<cpx> roots = {{0, 0}, {1, 0}};
void ensure_capacity(int min_capacity) {
    for (int len = roots.size(); len < min_capacity; len <<= 1) {
        for (int i = len >> 1; i < len; i++) {
            roots.emplace_back(roots[i]);
            double angle = 2 * PI * (2 * i + 1 - len) / (len << 1);
            roots.emplace_back(cos(angle), sin(angle));
        }
    }
}
void fft(vector<cpx>& z, bool inverse) {
    int n = z.size();
    ensure_capacity(n);
    for (unsigned i = 1, j = 0, bit; i < n; i++) {
        for (bit = n >> 1; j >= bit; bit >>= 1) j -= bit;
        j += bit;
        if (i < j) swap(z[i], z[j]);
    }
    for (int len = 1; len < n; len <<= 1) {
        for (int i = 0; i < n; i += len << 1) {
            for (int j = 0; j < len; j++) {
                cpx root = inverse ? conj(roots[j + len]) : roots[j + len];
                cpx u = z[i + j];
                cpx v = z[i + j + len] * root;
                z[i + j] = u + v;
                z[i + j + len] = u - v;
            }
        }
    }
    if (inverse)
        for (int i = 0; i < n; i++) z[i] /= n;
}
vector<int> multiply_bigint(const vector<int>& a, const vector<int>& b, int base) {
    int need = a.size() + b.size(), n = 1;
    while (n < need) n <<= 1;
    vector<cpx> p(n);
    for (size_t i = 0; i < n; i++) p[i] = cpx(i < a.size() ? a[i] : 0, i < b.size() ? b[i] : 0);
    fft(p, false);
    vector<cpx> ab(n);
    cpx r(0, -0.25);
    for (int i = 0, j; i < n; i++) j = (n - i) & (n - 1), ab[i] = (p[i] * p[i] - conj(p[j] * p[j])) * r;
    fft(ab, true);
    vector<int> result(need);
    long long carry = 0;
    for (int i = 0; i < need; i++) {
        long long d = (long long)(ab[i].real() + 0.5) + carry;
        carry = d / base;
        result[i] = d % base;
    }
    return result;
}
constexpr int fft_BASE = (int)1e4;  // fft_base^2 * n / fft_WS <= 10^15 for double
constexpr int fft_WS = 4;
}  // namespace FFT

struct ubigint : public vector<int> {
    const static int BASE = (int)1e4;
    const static int WS = 4;  // change with BASE
    static vector<int> convert_base(const vector<int>::const_iterator& beg, size_t sz, int old_digits, int new_digits) {
        if (old_digits == new_digits) return vector<int>(beg, beg + sz);
        vector<int> p(std::max(old_digits, new_digits) + 1);
        p[0] = 1;
        for (int i = 1; i < p.size(); i++) p[i] = p[i - 1] * 10;
        vector<int> res;
        long long cur = 0;
        int cur_digits = 0;
        for (size_t i = 0; i < sz; ++i) {
            cur += 1ll * *(beg + i) * p[cur_digits];
            cur_digits += old_digits;
            while (cur_digits >= new_digits) {
                res.emplace_back(cur % p[new_digits]);
                cur /= p[new_digits];
                cur_digits -= new_digits;
            }
        }
        res.emplace_back((int)cur);
        while (!res.empty() && !res.back()) res.pop_back();
        return res;
    }
    ubigint() {}
    ubigint(int t) : vector<int>(1, t) {}
    ubigint(long long t) {
        while (t) emplace_back(t % BASE);
    }
    ubigint(const vector<int>& v) : vector<int>(v) {}
    ubigint(string s) {
        for (int i = s.size() - 1, j, t; i >= 0; i -= WS) {
            for (j = max(0, i - WS + 1), t = 0; j <= i; ++j) t = (t * 10 + (s[j] - '0'));
            emplace_back(t);
        }
    }
    unsigned int digits() const {
        if (isZero()) return 1;
        unsigned int d = (size() - 1u) * WS;
        int x = back();
        while (x) ++d, x /= 10;
        return d;
    }
    const bool isZero() const { return empty() or (size() == 1u and !front()); }
    int const& operator[](const int n) const { return (n < size()) ? *(cbegin() + n) : (int const&)0; }
    int& operator[](const int n) { return *(begin() + n); }
    operator string() {
        if (isZero()) return "0";
        string ans;
        stringstream ss;
        ss << back();
        for (int i = (int)size() - 2; ~i; --i) ss << setw(WS) << setfill('0') << *(begin() + i);
        ss >> ans;
        return ans;
    }
    friend void read(ubigint& a) {
        string s;
        char c = getchar();
        while (!isdigit(c)) c = getchar();
        while (isdigit(c)) s.push_back(c), c = getchar();
        a = ubigint(s);
    }
    friend void print(const ubigint& a) {
        if (a.isZero()) return (void)putchar('0');
        printf("%d", a.back());
        for (int i = (int)a.size() - 2; ~i; --i) printf("%0*d", WS, a[i]);
    }
    friend bool operator==(ubigint const& a, ubigint const& b) {
        if (a.size() != b.size()) return 0;
        for (int i = 0; i < (int)a.size(); ++i)
            if (a[i] != b[i]) return 0;
        return 1;
    }
    friend bool operator!=(ubigint const& a, ubigint const& b) { return !(a == b); }
    friend bool operator<(ubigint const& a, ubigint const& b) {
        if (a.size() != b.size()) return a.size() < b.size();
        for (int i = (int)a.size() - 1; ~i; --i)
            if (a[i] != b[i]) return a[i] < b[i];
        return 0;
    }
    friend bool operator>(ubigint const& a, ubigint const& b) { return b < a; }
    friend bool operator<=(ubigint const& a, ubigint const& b) {
        if (a.size() != b.size()) return a.size() < b.size();
        for (int i = (int)a.size() - 1; ~i; --i)
            if (a[i] != b[i]) return a[i] < b[i];
        return 1;
    }
    friend bool operator>=(ubigint const& a, ubigint const& b) { return b <= a; }
    friend ubigint operator+(ubigint const& a, ubigint const& b) {
        ubigint c = a;
        c.resize(max(a.size(), b.size()) + 1);
        for (int i = 0, en = b.size(); i < en; ++i) {
            c[i] += b[i];
            if (c[i] >= BASE) c[i] -= BASE, ++c[i + 1];
        }
        for (int i = b.size(), en = c.size() - 1; i < en; ++i)
            if (c[i] >= BASE) c[i] -= BASE, ++c[i + 1];
        if (!c.back()) c.pop_back();
        return c;
    }
    friend ubigint operator-(ubigint const& a, ubigint const& b) {
        ubigint c = a;
        for (int i = 0, en = b.size(); i < en; ++i) {
            c[i] -= b[i];
            if (c[i] < 0) c[i] += BASE, --c[i + 1];
        }
        for (int i = b.size(), en = c.size(); i < en; ++i) {
            if (c[i] < 0)
                c[i] += BASE, --c[i + 1];
            else
                break;
        }
        while (c.size() > 1u && !c.back()) c.pop_back();
        return c;
    }
    friend ubigint operator*(ubigint const& a, int o) {
        if (!o or a.isZero()) return 0;
        int n = a.size();
        ubigint c;
        c.resize(n);
        long long carry = 0;
        for (int i = 0; i < n; ++i) {
            carry += (long long)a[i] * o;
            c[i] = carry % BASE;
            carry /= BASE;
        }
        if (carry) c.emplace_back(carry);
        return c;
    }
    friend ubigint operator*(ubigint const& a, ubigint const& b) {
        if (a.isZero() or b.isZero()) return 0;
        ubigint res(FFT::multiply_bigint(convert_base(a.begin(), a.size(), WS, FFT::fft_WS), convert_base(b.cbegin(), b.size(), WS, FFT::fft_WS), FFT::fft_BASE));
        res = convert_base(res.begin(), res.size(), FFT::fft_WS, WS);
        while (!res.empty() and !res.back()) res.pop_back();
        return res;
    }

    friend ubigint operator/(ubigint const& a, ubigint const& b) {
        assert(!b.isZero());
        if (a.size() < b.size()) return 0;
        ubigint c, d;
        c.assign(a.end() - b.size() + 1, a.end());
        for (int i = a.size() - b.size(); ~i; --i) {
            c.insert(c.begin(), *(a.begin() + i));
            long long t = (c.size() > b.size()) ? ((long long)c.back() * BASE + *(c.crbegin() + 1)) : c.back();
            int l = (t / (b.back() + 1)), r = ((t + 1) / b.back()), mid;
            while (l < r) {
                mid = (l + r + 1) >> 1;
                if (b * mid <= c)
                    l = mid;
                else
                    r = mid - 1;
            }
            c -= b * l;
            if (!c.back()) c.pop_back();
            d.emplace_back(l);
        }
        reverse(d.begin(), d.end());
        if (d.size() > 1u && !d.back()) d.pop_back();
        return d;
    }
    friend ubigint divide(ubigint const& a, ubigint const& b, ubigint& c) {
        assert(!b.isZero());
        if (a.size() < b.size() or a.isZero()) return c = a, 0;
        ubigint d;
        c.assign(a.end() - b.size() + 1, a.end());
        for (int i = a.size() - b.size(); ~i; --i) {
            c.insert(c.begin(), *(a.begin() + i));
            long long t = (c.size() > b.size()) ? ((long long)c.back() * BASE + *(c.crbegin() + 1)) : c.back();
            int l = (t / (b.back() + 1)), r = ((t + 1) / b.back()), mid;
            while (l < r) {
                mid = (l + r + 1) >> 1;
                if (b * mid <= c)
                    l = mid;
                else
                    r = mid - 1;
            }
            c -= b * l;
            if (!c.back()) c.pop_back();
            d.emplace_back(l);
        }
        reverse(d.begin(), d.end());
        if (d.size() > 1u && !d.back()) d.pop_back();
        return d;
    }
    friend ubigint operator%(ubigint const& a, ubigint const& b) { return a - a / b * b; }
    friend ubigint const& operator+=(ubigint& a, ubigint const& b) { return a = a + b; }
    friend ubigint const& operator-=(ubigint& a, ubigint const& b) { return a = a - b; }
    friend ubigint const& operator*=(ubigint& a, int const& b) { return a = a * b; }
    friend ubigint const& operator*=(ubigint& a, ubigint const& b) { return a = a * b; }
    friend ubigint const& operator/=(ubigint& a, ubigint const& b) { return a = a / b; }
    friend ubigint const& operator%=(ubigint& a, ubigint const& b) { return a = a % b; }
};
struct bigint {
    bool f;
    ubigint t;
    bigint() : f(0) {}
    bigint(int t) : f(t < 0), t(ubigint(abs(t))) {}
    bigint(long long x) : f(x < 0) {
        while (x) t.emplace_back(x);
    }
    bigint(bool f, ubigint t) : f(f), t(t) {}
    bigint(const vector<int>& a) : t(a) {}
    unsigned int digits() const { return t.digits(); }
    const bool isZero() const { return t.isZero(); }
    int const& operator[](const int n) const { return (n < t.size()) ? *(t.cbegin() + n) : (int const&)0; }
    int& operator[](const int n) { return *(t.begin() + n); }
    operator string() {
        if (t.isZero()) return "0";
        string ans;
        stringstream ss;
        if (f) ss << '-';
        ss << t.back();
        for (int i = (int)t.size() - 2; ~i; --i) ss << setw(t.WS) << setfill('0') << t[i];
        ss >> ans;
        return ans;
    }
    friend void read(bigint& a) {
        a.f = 0;
        string s;
        char c = getchar();
        for (; !isdigit(c); c = getchar())
            if (c == '-') a.f = 1;
        while (isdigit(c)) s.push_back(c), c = getchar();
        a.t = ubigint(s);
    }
    friend void print(const bigint& a) {
        if (a.t.isZero()) return (void)putchar('0');
        if (a.f) putchar('-');
        print(a.t);
    }
    friend bigint abs(bigint const& a) { return bigint(0, a.t); }
    friend bool operator==(bigint const& a, bigint const& b) { return (a.f == b.f) && (a.t == b.t); }
    friend bool operator!=(bigint const& a, bigint const& b) { return !(a == b); }
    friend bool operator<(bigint const& a, bigint const& b) {
        if (a.f != b.f) return a.f;
        return a.f ? a.t > b.t : a.t < b.t;
    }
    friend bool operator>(bigint const& a, bigint const& b) { return b < a; }
    friend bool operator<=(bigint const& a, bigint const& b) {
        if (a.f != b.f) return a.f;
        return a.f ? a.t >= b.t : a.t <= b.t;
    }
    friend bool operator>=(bigint const& a, bigint const& b) { return b <= a; }
    friend bigint operator-(bigint const& a) { return bigint(!a.f, a.t); }
    friend bigint operator+(bigint const& a, bigint const& b) {
        if (a.f == b.f) return bigint(a.f, a.t + b.t);
        if (a.t > b.t) return bigint(a.f, a.t - b.t);
        if (a.t < b.t) return bigint(b.f, b.t - a.t);
        return 0;
    }
    friend bigint operator-(bigint const& a, bigint const& b) {
        if (a.f == b.f) {
            if (a.t > b.t) return bigint(a.f, a.t - b.t);
            if (a.t < b.t) return bigint(!a.f, b.t - a.t);
            return 0;
        }
        return bigint(a.f, a.t + b.t);
    }
    friend bigint operator*(bigint const& a, bigint const& b) { return bigint(a.f ^ b.f, a.t * b.t); }
    friend bigint operator*(bigint const& a, int const& b) { return bigint(a.f ^ (b < 0), a.t * b); }
    friend bigint divide(bigint const& a, bigint const& b, bigint& c) { return bigint(a.f ^ b.f, divide(a.t, b.t, (c.f = a.f, c.t))); }
    friend bigint operator/(bigint const& a, bigint const& b) { return bigint(a.f ^ b.f, a.t / b.t); }
    friend bigint operator%(bigint const& a, bigint const& b) { return bigint(a.f, a.t % b.t); }
    friend bigint const& operator+=(bigint& a, bigint const& b) { return a = a + b; }
    friend bigint const& operator-=(bigint& a, bigint const& b) { return a = a - b; }
    friend bigint const& operator*=(bigint& a, int const& b) { return a = a * b; }
    friend bigint const& operator*=(bigint& a, bigint const& b) { return a = a * b; }
    friend bigint const& operator/=(bigint& a, bigint const& b) { return a = a / b; }
    friend bigint const& operator%=(bigint& a, bigint const& b) { return a = a % b; }
};
// don't close ios_base::sync_with_stdio

不加速

编译器无__int128(压1~8位)

Code
struct ubigint : public vector<int> {
    const static int BASE = (int)1e8;
    const static int WS = 8;  // change with BASE
    ubigint() {}
    ubigint(int t) : vector<int>(1, t) {}
    ubigint(long long x) {
        while (x) emplace_back(x);
    }
    ubigint(const vector<int>& a) : vector<int>(a) {}
    ubigint(string s) {
        for (int i = s.size() - 1, j, t; i >= 0; i -= WS) {
            for (j = max(0, i - WS + 1), t = 0; j <= i; ++j) t = (t * 10 + (s[j] - '0'));
            emplace_back(t);
        }
    }
    unsigned int digits() const {
        if (isZero()) return 1;
        unsigned int d = (size() - 1u) * WS;
        int x = back();
        while (x) ++d, x /= 10;
        return d;
    }
    const bool isZero() const { return empty() or (size() == 1u and !front()); }
    int const& operator[](const int n) const { return (n < size()) ? *(cbegin() + n) : (int const&)0; }
    int& operator[](const int n) { return *(begin() + n); }
    operator string() {
        if (isZero()) return "0";
        string ans;
        stringstream ss;
        ss << back();
        for (int i = (int)size() - 2; ~i; --i) ss << setw(WS) << setfill('0') << *(begin() + i);
        ss >> ans;
        return ans;
    }
    friend void read(ubigint& a) {
        string s;
        char c = getchar();
        while (!isdigit(c)) c = getchar();
        while (isdigit(c)) s.push_back(c), c = getchar();
        a = ubigint(s);
    }
    friend void print(const ubigint& a) {
        if (a.isZero()) return (void)putchar('0');
        printf("%d", a.back());
        for (int i = (int)a.size() - 2; ~i; --i) printf("%0*d", WS, a[i]);
    }
    friend bool operator==(ubigint const& a, ubigint const& b) {
        if (a.size() != b.size()) return 0;
        for (int i = 0; i < (int)a.size(); ++i)
            if (a[i] != b[i]) return 0;
        return 1;
    }
    friend bool operator!=(ubigint const& a, ubigint const& b) { return !(a == b); }
    friend bool operator<(ubigint const& a, ubigint const& b) {
        if (a.size() != b.size()) return a.size() < b.size();
        for (int i = (int)a.size() - 1; ~i; --i)
            if (a[i] != b[i]) return a[i] < b[i];
        return 0;
    }
    friend bool operator>(ubigint const& a, ubigint const& b) { return b < a; }
    friend bool operator<=(ubigint const& a, ubigint const& b) {
        if (a.size() != b.size()) return a.size() < b.size();
        for (int i = (int)a.size() - 1; ~i; --i)
            if (a[i] != b[i]) return a[i] < b[i];
        return 1;
    }
    friend bool operator>=(ubigint const& a, ubigint const& b) { return b <= a; }
    friend ubigint operator+(ubigint const& a, ubigint const& b) {
        ubigint c = a;
        c.resize(max(a.size(), b.size()) + 1);
        for (int i = 0, en = b.size(); i < en; ++i) {
            c[i] += b[i];
            if (c[i] >= BASE) c[i] -= BASE, ++c[i + 1];
        }
        for (int i = b.size(), en = c.size() - 1; i < en; ++i)
            if (c[i] >= BASE) c[i] -= BASE, ++c[i + 1];
        if (!c.back()) c.pop_back();
        return c;
    }
    friend ubigint operator-(ubigint const& a, ubigint const& b) {
        ubigint c = a;
        for (int i = 0, en = b.size(); i < en; ++i) {
            c[i] -= b[i];
            if (c[i] < 0) c[i] += BASE, --c[i + 1];
        }
        for (int i = b.size(), en = c.size(); i < en; ++i) {
            if (c[i] < 0)
                c[i] += BASE, --c[i + 1];
            else
                break;
        }
        while (c.size() > 1u && !c.back()) c.pop_back();
        return c;
    }
    friend ubigint operator*(ubigint const& a, int o) {
        if (!o or a.isZero()) return 0;
        int n = a.size();
        ubigint c;
        c.resize(n);
        long long carry = 0;
        for (int i = 0; i < n; ++i) {
            carry += (long long)a[i] * o;
            c[i] = carry % BASE;
            carry /= BASE;
        }
        if (carry) c.emplace_back(carry);
        return c;
    }
    friend ubigint operator*(ubigint const& a, ubigint const& b) {
        if (a.isZero() || b.isZero()) return 0;
        int sa = a.size(), sb = b.size();
        vector<long long> t(sa + sb);
        for (int i = 0; i < sa; ++i)
            for (int j = 0; j < sb; ++j) t[i + j] += (long long)a[i] * b[j];
        for (int i = 0, en = t.size() - 1; i < en; ++i) t[i + 1] += t[i] / BASE, t[i] %= BASE;
        if (!t.back()) t.pop_back();
        ubigint c;
        c.resize(t.size());
        for (int i = 0, en = t.size(); i < en; ++i) c[i] = (int)t[i];
        return c;
    }
    friend ubigint operator/(ubigint const& a, ubigint const& b) {
        assert(!b.isZero());
        if (a.size() < b.size()) return 0;
        ubigint c, d;
        c.assign(a.end() - b.size() + 1, a.end());
        for (int i = a.size() - b.size(); ~i; --i) {
            c.insert(c.begin(), *(a.begin() + i));
            long long t = (c.size() > b.size()) ? ((long long)c.back() * BASE + *(c.crbegin() + 1)) : c.back();
            int l = (t / (b.back() + 1)), r = ((t + 1) / b.back()), mid;
            while (l < r) {
                mid = (l + r + 1) >> 1;
                if (b * mid <= c)
                    l = mid;
                else
                    r = mid - 1;
            }
            c -= b * l;
            if (!c.back()) c.pop_back();
            d.emplace_back(l);
        }
        reverse(d.begin(), d.end());
        if (d.size() > 1u && !d.back()) d.pop_back();
        return d;
    }
    friend ubigint divide(ubigint const& a, ubigint const& b, ubigint& c) {
        assert(!b.isZero());
        if (a.size() < b.size() or a.isZero()) return c = a, 0;
        ubigint d;
        c.assign(a.end() - b.size() + 1, a.end());
        for (int i = a.size() - b.size(); ~i; --i) {
            c.insert(c.begin(), *(a.begin() + i));
            long long t = (c.size() > b.size()) ? ((long long)c.back() * BASE + *(c.crbegin() + 1)) : c.back();
            int l = (t / (b.back() + 1)), r = ((t + 1) / b.back()), mid;
            while (l < r) {
                mid = (l + r + 1) >> 1;
                if (b * mid <= c)
                    l = mid;
                else
                    r = mid - 1;
            }
            c -= b * l;
            if (!c.back()) c.pop_back();
            d.emplace_back(l);
        }
        reverse(d.begin(), d.end());
        if (d.size() > 1u && !d.back()) d.pop_back();
        return d;
    }
    friend ubigint operator%(ubigint const& a, ubigint const& b) { return a - a / b * b; }
    friend ubigint const& operator+=(ubigint& a, ubigint const& b) { return a = a + b; }
    friend ubigint const& operator-=(ubigint& a, ubigint const& b) { return a = a - b; }
    friend ubigint const& operator*=(ubigint& a, int const& b) { return a = a * b; }
    friend ubigint const& operator*=(ubigint& a, ubigint const& b) { return a = a * b; }
    friend ubigint const& operator/=(ubigint& a, ubigint const& b) { return a = a / b; }
    friend ubigint const& operator%=(ubigint& a, ubigint const& b) { return a = a % b; }
};
struct bigint {
    bool f;
    ubigint t;
    bigint() : f(0) {}
    bigint(int t) : f(t < 0), t(ubigint(abs(t))) {}
    bigint(long long x) : f(x < 0) {
        while (x) t.emplace_back(x);
    }
    bigint(const vector<int>& a) : t(a) {}
    bigint(bool f, ubigint t) : f(f), t(t) {}
    unsigned int digits() const { return t.digits(); }
    const bool isZero() const { return t.isZero(); }
    int const& operator[](const int n) const { return (n < t.size()) ? *(t.cbegin() + n) : (int const&)0; }
    int& operator[](const int n) { return *(t.begin() + n); }
    operator string() {
        if (t.isZero()) return "0";
        string ans;
        stringstream ss;
        if (f) ss << '-';
        ss << t.back();
        for (int i = (int)t.size() - 2; ~i; --i) ss << setw(t.WS) << setfill('0') << t[i];
        ss >> ans;
        return ans;
    }
    friend void read(bigint& a) {
        a.f = 0;
        string s;
        char c = getchar();
        for (; !isdigit(c); c = getchar())
            if (c == '-') a.f = 1;
        while (isdigit(c)) s.push_back(c), c = getchar();
        a.t = ubigint(s);
    }
    friend void print(const bigint& a) {
        if (a.t.isZero()) return (void)putchar('0');
        if (a.f) putchar('-');
        print(a.t);
    }
    friend bigint abs(bigint const& a) { return bigint(0, a.t); }
    friend bool operator==(bigint const& a, bigint const& b) { return (a.f == b.f) && (a.t == b.t); }
    friend bool operator!=(bigint const& a, bigint const& b) { return !(a == b); }
    friend bool operator<(bigint const& a, bigint const& b) {
        if (a.f != b.f) return a.f;
        return a.f ? a.t > b.t : a.t < b.t;
    }
    friend bool operator>(bigint const& a, bigint const& b) { return b < a; }
    friend bool operator<=(bigint const& a, bigint const& b) {
        if (a.f != b.f) return a.f;
        return a.f ? a.t >= b.t : a.t <= b.t;
    }
    friend bool operator>=(bigint const& a, bigint const& b) { return b <= a; }
    friend bigint operator-(bigint const& a) { return bigint(!a.f, a.t); }
    friend bigint operator+(bigint const& a, bigint const& b) {
        if (a.f == b.f) return bigint(a.f, a.t + b.t);
        if (a.t > b.t) return bigint(a.f, a.t - b.t);
        if (a.t < b.t) return bigint(b.f, b.t - a.t);
        return 0;
    }
    friend bigint operator-(bigint const& a, bigint const& b) {
        if (a.f == b.f) {
            if (a.t > b.t) return bigint(a.f, a.t - b.t);
            if (a.t < b.t) return bigint(!a.f, b.t - a.t);
            return 0;
        }
        return bigint(a.f, a.t + b.t);
    }
    friend bigint operator*(bigint const& a, bigint const& b) { return bigint(a.f ^ b.f, a.t * b.t); }
    friend bigint operator*(bigint const& a, int const& b) { return bigint(a.f ^ (b < 0), a.t * b); }
    friend bigint divide(bigint const& a, bigint const& b, bigint& c) { return bigint(a.f ^ b.f, divide(a.t, b.t, (c.f = a.f, c.t))); }
    friend bigint operator/(bigint const& a, bigint const& b) { return bigint(a.f ^ b.f, a.t / b.t); }
    friend bigint operator%(bigint const& a, bigint const& b) { return bigint(a.f, a.t % b.t); }
    friend bigint const& operator+=(bigint& a, bigint const& b) { return a = a + b; }
    friend bigint const& operator-=(bigint& a, bigint const& b) { return a = a - b; }
    friend bigint const& operator*=(bigint& a, int const& b) { return a = a * b; }
    friend bigint const& operator*=(bigint& a, bigint const& b) { return a = a * b; }
    friend bigint const& operator/=(bigint& a, bigint const& b) { return a = a / b; }
    friend bigint const& operator%=(bigint& a, bigint const& b) { return a = a % b; }
    // don't close ios_base::sync_with_stdio
};

编译器有__int128(压1~18位)

不知道为什么测试速度不如压8位的

Code
struct ubigint : public vector<long long> {
    const static long long BASE = (long long)1e18;
    const static int WS = 18;  // change with BASE
    ubigint() {}
    ubigint(long long t) : vector<long long>(1, t) {}
    ubigint(const vector<long long>& a) : vector<long long>(a) {}
    ubigint(string s) {
        for (int i = s.size() - 1, j; i >= 0; i -= WS) {
            long long t = 0;
            for (j = max(0, i - WS + 1); j <= i; ++j) t = (t * 10ll + (s[j] - '0'));
            emplace_back(t);
        }
    }
    unsigned int digits() const {
        if (isZero()) return 1;
        unsigned int d = (size() - 1u) * WS;
        long long x = back();
        while (x) ++d, x /= 10ll;
        return d;
    }
    const bool isZero() const { return empty() or (size() == 1u and !front()); }
    long long const& operator[](const int n) const { return (n < size()) ? *(cbegin() + n) : (long long const&)0; }
    long long& operator[](const int n) { return *(begin() + n); }
    operator string() {
        if (isZero()) return "0";
        string ans;
        stringstream ss;
        ss << back();
        for (int i = (int)size() - 2; ~i; --i) ss << setw(WS) << setfill('0') << *(begin() + i);
        ss >> ans;
        return ans;
    }
    friend void read(ubigint& a) {
        string s;
        char c = getchar();
        while (!isdigit(c)) c = getchar();
        while (isdigit(c)) s.push_back(c), c = getchar();
        a = ubigint(s);
    }
    friend void print(const ubigint& a) {
        if (a.isZero()) return (void)putchar('0');
        printf("%lld", a.back());
        for (int i = (int)a.size() - 2; ~i; --i) printf("%0*lld", WS, a[i]);
    }
    friend bool operator==(ubigint const& a, ubigint const& b) {
        if (a.size() != b.size()) return 0;
        for (int i = 0; i < (int)a.size(); ++i)
            if (a[i] != b[i]) return 0;
        return 1;
    }
    friend bool operator!=(ubigint const& a, ubigint const& b) { return !(a == b); }
    friend bool operator<(ubigint const& a, ubigint const& b) {
        if (a.size() != b.size()) return a.size() < b.size();
        for (int i = (int)a.size() - 1; ~i; --i)
            if (a[i] != b[i]) return a[i] < b[i];
        return 0;
    }
    friend bool operator>(ubigint const& a, ubigint const& b) { return b < a; }
    friend bool operator<=(ubigint const& a, ubigint const& b) {
        if (a.size() != b.size()) return a.size() < b.size();
        for (int i = (int)a.size() - 1; ~i; --i)
            if (a[i] != b[i]) return a[i] < b[i];
        return 1;
    }
    friend bool operator>=(ubigint const& a, ubigint const& b) { return b <= a; }
    friend ubigint operator+(ubigint const& a, ubigint const& b) {
        ubigint c = a;
        c.resize(max(a.size(), b.size()) + 1);
        for (int i = 0, en = b.size(); i < en; ++i) {
            c[i] += b[i];
            if (c[i] >= BASE) c[i] -= BASE, ++c[i + 1];
        }
        for (int i = b.size(), en = c.size() - 1; i < en; ++i)
            if (c[i] >= BASE) c[i] -= BASE, ++c[i + 1];
        if (!c.back()) c.pop_back();
        return c;
    }
    friend ubigint operator-(ubigint const& a, ubigint const& b) {
        ubigint c = a;
        for (int i = 0, en = b.size(); i < en; ++i) {
            c[i] -= b[i];
            if (c[i] < 0ll) c[i] += BASE, --c[i + 1];
        }
        for (int i = b.size(), en = c.size(); i < en; ++i) {
            if (c[i] < 0ll)
                c[i] += BASE, --c[i + 1];
            else
                break;
        }
        while (c.size() > 1u && !c.back()) c.pop_back();
        return c;
    }
    friend ubigint operator*(ubigint const& a, long long o) {
        if (!o or a.isZero()) return 0;
        int n = a.size();
        ubigint c;
        c.resize(n);
        __int128_t carry = 0;
        for (int i = 0; i < n; ++i) {
            carry += (__int128_t)a[i] * o;
            c[i] = carry % BASE;
            carry /= BASE;
        }
        if (carry) c.emplace_back(carry);
        return c;
    }
    friend ubigint operator*(ubigint const& a, ubigint const& b) {
        if (a.isZero() || b.isZero()) return 0ll;
        int sa = a.size(), sb = b.size();
        vector<__int128_t> t(sa + sb);
        for (int i = 0; i < sa; ++i)
            for (int j = 0; j < sb; ++j) t[i + j] += (__int128_t)a[i] * b[j];
        for (int i = 0, en = t.size() - 1; i < en; ++i) t[i + 1] += t[i] / BASE, t[i] %= BASE;
        if (!t.back()) t.pop_back();
        ubigint c;
        c.resize(t.size());
        for (int i = 0, en = t.size(); i < en; ++i) c[i] = (long long)t[i];
        return c;
    }
    friend ubigint operator/(ubigint const& a, ubigint const& b) {
        assert(!b.isZero());
        if (a.size() < b.size()) return 0;
        ubigint c, d;
        c.assign(a.end() - b.size() + 1, a.end());
        for (int i = a.size() - b.size(); ~i; --i) {
            c.insert(c.begin(), *(a.begin() + i));
            __int128_t t = (c.size() > b.size()) ? ((__int128_t)c.back() * BASE + *(c.crbegin() + 1)) : c.back();
            long long l = (t / (b.back() + 1ll)), r = ((t + 1) / b.back()), mid;
            while (l < r) {
                mid = (l + r + 1ll) >> 1;
                if (b * mid <= c)
                    l = mid;
                else
                    r = mid - 1ll;
            }
            c -= b * l;
            if (!c.back()) c.pop_back();
            d.emplace_back(l);
        }
        reverse(d.begin(), d.end());
        if (d.size() > 1u && !d.back()) d.pop_back();
        return d;
    }
    friend ubigint divide(ubigint const& a, ubigint const& b, ubigint& c) {
        assert(!b.isZero());
        if (a.size() < b.size() or a.isZero()) return c = a, 0;
        ubigint d;
        c.assign(a.end() - b.size() + 1, a.end());
        for (int i = a.size() - b.size(); ~i; --i) {
            c.insert(c.begin(), *(a.begin() + i));
            __int128_t t = (c.size() > b.size()) ? ((__int128_t)c.back() * BASE + *(c.crbegin() + 1)) : c.back();
            long long l = (t / (b.back() + 1ll)), r = ((t + 1) / b.back()), mid;
            while (l < r) {
                mid = (l + r + 1ll) >> 1;
                if (b * mid <= c)
                    l = mid;
                else
                    r = mid - 1ll;
            }
            c -= b * l;
            if (!c.back()) c.pop_back();
            d.emplace_back(l);
        }
        reverse(d.begin(), d.end());
        if (d.size() > 1u && !d.back()) d.pop_back();
        return d;
    }
    friend ubigint operator%(ubigint const& a, ubigint const& b) { return a - a / b * b; }
    friend ubigint const& operator+=(ubigint& a, ubigint const& b) { return a = a + b; }
    friend ubigint const& operator-=(ubigint& a, ubigint const& b) { return a = a - b; }
    friend ubigint const& operator*=(ubigint& a, long long const& b) { return a = a * b; }
    friend ubigint const& operator*=(ubigint& a, ubigint const& b) { return a = a * b; }
    friend ubigint const& operator/=(ubigint& a, ubigint const& b) { return a = a / b; }
    friend ubigint const& operator%=(ubigint& a, ubigint const& b) { return a = a % b; }
};
struct bigint {
    bool f;
    ubigint t;
    bigint() : f(0) {}
    bigint(long long t) : f(t < 0), t(ubigint(abs(t))) {}
    bigint(const vector<long long>& a) : t(a) {}
    bigint(bool f, ubigint t) : f(f), t(t) {}
    unsigned int digits() const { return t.digits(); }
    const bool isZero() const { return t.isZero(); }
    long long const& operator[](const int n) const { return (n < t.size()) ? *(t.cbegin() + n) : (long long const&)0; }
    long long& operator[](const int n) { return *(t.begin() + n); }
    operator string() {
        if (t.isZero()) return "0";
        string ans;
        stringstream ss;
        if (f) ss << '-';
        ss << t.back();
        for (int i = (int)t.size() - 2; ~i; --i) ss << setw(t.WS) << setfill('0') << t[i];
        ss >> ans;
        return ans;
    }
    friend void read(bigint& a) {
        a.f = 0;
        string s;
        char c = getchar();
        for (; !isdigit(c); c = getchar())
            if (c == '-') a.f = 1;
        while (isdigit(c)) s.push_back(c), c = getchar();
        a.t = ubigint(s);
    }
    friend void print(const bigint& a) {
        if (a.t.isZero()) return (void)putchar('0');
        if (a.f) putchar('-');
        print(a.t);
    }
    friend bigint abs(bigint const& a) { return bigint(0, a.t); }
    friend bool operator==(bigint const& a, bigint const& b) { return (a.f == b.f) && (a.t == b.t); }
    friend bool operator!=(bigint const& a, bigint const& b) { return !(a == b); }
    friend bool operator<(bigint const& a, bigint const& b) {
        if (a.f != b.f) return a.f;
        return a.f ? a.t > b.t : a.t < b.t;
    }
    friend bool operator>(bigint const& a, bigint const& b) { return b < a; }
    friend bool operator<=(bigint const& a, bigint const& b) {
        if (a.f != b.f) return a.f;
        return a.f ? a.t >= b.t : a.t <= b.t;
    }
    friend bool operator>=(bigint const& a, bigint const& b) { return b <= a; }
    friend bigint operator-(bigint const& a) { return bigint(!a.f, a.t); }
    friend bigint operator+(bigint const& a, bigint const& b) {
        if (a.f == b.f) return bigint(a.f, a.t + b.t);
        if (a.t > b.t) return bigint(a.f, a.t - b.t);
        if (a.t < b.t) return bigint(b.f, b.t - a.t);
        return 0;
    }
    friend bigint operator-(bigint const& a, bigint const& b) {
        if (a.f == b.f) {
            if (a.t > b.t) return bigint(a.f, a.t - b.t);
            if (a.t < b.t) return bigint(!a.f, b.t - a.t);
            return 0;
        }
        return bigint(a.f, a.t + b.t);
    }
    friend bigint operator*(bigint const& a, bigint const& b) { return bigint(a.f ^ b.f, a.t * b.t); }
    friend bigint operator*(bigint const& a, long long const& b) { return bigint(a.f ^ (b < 0), a.t * b); }
    friend bigint divide(bigint const& a, bigint const& b, bigint& c) { return bigint(a.f ^ b.f, divide(a.t, b.t, (c.f = a.f, c.t))); }
    friend bigint operator/(bigint const& a, bigint const& b) { return bigint(a.f ^ b.f, a.t / b.t); }
    friend bigint operator%(bigint const& a, bigint const& b) { return bigint(a.f, a.t % b.t); }
    friend bigint const& operator+=(bigint& a, bigint const& b) { return a = a + b; }
    friend bigint const& operator-=(bigint& a, bigint const& b) { return a = a - b; }
    friend bigint const& operator*=(bigint& a, long long const& b) { return a = a * b; }
    friend bigint const& operator*=(bigint& a, bigint const& b) { return a = a * b; }
    friend bigint const& operator/=(bigint& a, bigint const& b) { return a = a / b; }
    friend bigint const& operator%=(bigint& a, bigint const& b) { return a = a % b; }
    // don't close ios_base::sync_with_stdio
};

标签:return,高精度,ubigint,bigint,const,friend,size
来源: https://www.cnblogs.com/Cattle-Horse/p/16608015.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有