高精度
2022/8/20 23:56:14
本文主要是介绍高精度,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
高精度
以下均为压位高精度 高精度除高精度以二分法求
以下均含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 };
这篇关于高精度的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南