首页 > 其他分享 >高精度

高精度

时间:2022-08-20 16:34:43浏览次数:44  
标签: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
From: https://www.cnblogs.com/Cattle-Horse/p/16608015.html

相关文章

  • 高精度a+b
    高精度a+bacwing3596.a+b存在vector<int>中去,倒着存,低位在前,高位在后代码#include<iostream>#include<vector>#include<cstring>usingnamespacestd;vector<i......