template

· · 个人记录

线段树

struct Seg {
    struct SegMent {

    } ;

    inline int ls(int p) {return p << 1;}
    inline int rs(int p) {return p << 1 | 1;}

    inline void clone(int p) {
    }

    inline ll get(int p) {
        return 0ll;
    }

    ll oper(ll pl, ll pr) {
        return 0ll;
    }

    void build(int p, int l, int r) {
        int mid = (l + r) >> 1;
        build(ls(p), l, mid), build(rs(p), mid + 1, r);
    }

    void pushdown(int p) {
    }

    void pushup(int p) {
    }

    void ins(int p, int l, int r, int x, ll v) {
        int mid = (l + r) >> 1;
        if(x <= mid) ins(ls(p), l, mid, x, v);
        else ins(rs(p), mid + 1, r, x, v);
        pushup(p);
    }

    void upd(int p, int l, int r, int ql, int qr, ll v) {
        int mid = (l + r) >> 1;
        if(mid >= qr) upd(ls(p), l, mid, ql, qr, v);
        else if(mid + 1 <= ql) upd(rs(p), mid + 1, r, ql, qr, v);
        else upd(ls(p), l, mid, ql, mid, v), upd(rs(p), mid + 1, r, mid + 1, qr, v);
        pushup(p);
    }

    ll que(int p, int l, int r, int ql, int qr) {
        int mid = (l + r) >> 1;
        if(mid >= qr) return que(ls(p), l, mid, ql, qr);
        else if(mid + 1 <= ql) return que(rs(p), mid + 1, r, ql, qr);
        else return oper(que(ls(p), l, mid, ql, mid), que(rs(p), mid + 1, r, mid + 1, qr));
    }

    int merge(int p1, int p2, int l, int r) {
        int mid = (l + r) >> 1;
        merge(ls(p1), ls(p2), l, mid);
        merge(rs(p1), rs(p2), mid + 1, r);
        pushup(p1); return p1;
    }
} ;

自动取模整类型

注:/ 相关运算仅支持模数 p 为质数,且复杂度为 \mathcal{O}(\log p)

template <int p> 
struct Int {
    static_assert(p != 0, "`Mod` must not be equal to 0.");
    static constexpr int getMod() { return p; }

    int a;  

    constexpr Int(): a(0) {}
    template <typename T, std::enable_if_t<std::is_signed_v<T>> * = nullptr>
    constexpr Int(T b): a(b % p + (b < 0 ? p : 0)) {}
    template <typename T, std::enable_if_t<std::is_unsigned_v<T>> * = nullptr>
    constexpr Int(T b): a(b % p) {}

    constexpr Int& operator += (const Int &b) {a += b.a; if(a >= p) a -= p; return *this;}
    constexpr Int& operator -= (const Int &b) {a -= b.a; if (a < 0) a += p; return *this;}
    constexpr Int& operator *= (const Int &b) {a = (ll)a * b.a % p; return *this;}
    constexpr Int& operator /= (const Int &b) {a = (ll)a * b.pow(p - 2).a % p; return *this;}
    friend constexpr Int operator + (const Int &x, const Int &y) {return Int<p>(x) += y;}
    friend constexpr Int operator - (const Int &x, const Int &y) {return Int<p>(x) -= y;}
    friend constexpr Int operator * (const Int &x, const Int &y) {return Int<p>(x) *= y;}
    friend constexpr Int operator / (const Int &x, const Int &y) {return Int<p>(x) /= y;}
    friend bool operator == (const Int &x, const Int &y) {return x.a == y.a;}
    friend bool operator != (const Int &x, const Int &y) {return x.a != y.a;}

    constexpr Int pow(ll b) const {
        Int<p> base = *this, res = 1;
        while(b) {
            if(b & 1) res *= base;
            b >>= 1; base *= base;
        }
        return res;
    }

    friend istream& operator >> (istream& In, Int& x) {
        ll val; In >> val; x.a = val % p + (val < 0 ? p : 0);
        return In;  
    }
    friend ostream& operator << (ostream& Out, const Int& x) {
        return Out << x.a;
    }
};
```cpp namespace Math { const int Math_N = 100005; const int Math_M = 1000005; ll frac[Math_N], ifrac[Math_N], inv[Math_N]; int prime[Math_M], vis[Math_M], cnt; void init(int n, ll p = Mod) { cerr << "MathInit Info." << '\n'; cerr << "N = " << Math_N << '\n'; frac[0] = 1; for(int i = 1; i <= n; ++i) frac[i] = frac[i - 1] * i % p; ifrac[n] = qpow(frac[n], p - 2, p); for(int i = n - 1; i >= 0; --i) ifrac[i] = ifrac[i + 1] * (i + 1) % p; inv[1] = 1; for(int i = 2; i <= n; ++i) inv[i] = (p - p / i) * inv[p % i] % p; } void getPrime(int n) { cerr << "MathInit Info." << '\n'; cerr << "M = " << Math_M << '\n'; for(int i = 2; i <= n; ++i) { if(vis[i] == 0) prime[++cnt] = i; for(int j = 1; j <= cnt && i * prime[j] <= n; ++j) { vis[i * prime[j]] = 1; if(i % prime[j] == 0) break; } } cerr << "cnt: " << cnt << '\n'; } ll comb(ll a, ll b, ll p = Mod) { if(a < b || b < 0) return 0ll; else return frac[a] * ifrac[b] % p * ifrac[a - b] % p; } ll perm(ll a, ll b, ll p = Mod) { if(a < b || b < 0) return 0ll; else return frac[a] * ifrac[a - b] % p; } ll lucas(ll a, ll b, ll p = Mod) { if(a < b || b < 0) return 0ll; if(b == 0) return 1ll; else return lucas(a / p, b / p) * comb(a % p, b % p) % p; } ll exgcd(ll a, ll b, ll &x, ll &y) { if(b == 0) { x = 1, y = 0; return a; } ll g = exgcd(b, a % b, x, y), z = x; x = y, y = z - y * (a / b); return g; } } using namespace Math; ``` vector 封装类 ```cpp template <typename T> class vect { private: T *a = new T[1]; int it = 0, _size = 1; public: void clear() { a = new T[1]; it = 0, _size = 1; } void resize(int n, int val = 0) { a = new T[n + 5]; it = 0, _size = n + 5; for(; it < n; ++it) a[it] = val; } void push_back(int x) { a[it++] = x; if(it == _size) { _size *= 2; T *b = a; a = new T[_size]; for(int i = 0; i < it; ++i) { a[i] = b[i]; } delete[] b; } } void pop_back() { assert(!empty()); it--; } T& operator [] (const int i) { return a[i]; } T& at(int i) { return operator[](i); } int size() { return it; } int load(){ return _size; } auto begin() { return a; } auto end() { return a + it; } bool empty(){ return (size() == 0); } T Min() { assert(!empty()); int res = a[0]; for(int i = 1; i < it; ++i) res = min(res, a[i]); return res; } int _Min() { assert(!empty()); int p = 0; for(int i = 1; i < it; ++i) if(a[p] > a[i]) p = i; return p; } T Max() { assert(!empty()); T res = a[0]; for(int i = 1; i < it; ++i) res = max(res, a[i]); return res; } int _Max() { assert(!empty()); int p = 0; for(int i = 1; i < it; ++i) if(a[p] < a[i]) p = i; return p; } int count(int x) { int res = 0; for(int i = 0; i < it; ++i) res += (a[i] == x); return res; } }; ``` 组合数学 ```cpp template <int p> struct Combinatorics { using T = Int<p>; // O(n * m) static vector<vector<T>> init_comb(int n, int m) { vector<vector<T>> c(n + 1, vector<T>(m + 1)); for(int i = 0; i <= n; ++i) for(int j = 0;j <= min(i, m); ++j) c[i][j] = (i && j) ? (c[i - 1][j - 1] + c[i - 1][j]) : (1); return c; } int _size = 0; vector<T> inv, fact, ifact; Combinatorics() {} // O(n) Combinatorics(int n): _size(n), inv(n + 5, 1), fact(n + 5, 1), ifact(n + 5, 1) { for(int i = 1; i <= n; ++i) fact[i] = fact[i - 1] * i; ifact[n] = 1 / fact[n]; for(int i = n - 1; i >= 0; --i) ifact[i] = ifact[i + 1] * (i + 1), inv[i + 1] = ifact[i + 1] * fact[i]; } // O(1) T comb(int a, int b) const { assert(max(a, b) <= _size); return (a >= b && b >= 0) ? (fact[a] * ifact[b] * ifact[a - b]) : (0); } // O(1) T perm(int a, int b) const { assert(max(a, b) <= _size); return (a >= b && b >= 0) ? (fact[a] * ifact[a - b]) : (0); } // O(1) T ban(int a, int b, int c = 1) const { assert(max(a - (ll)b * (c - 1) - 1, (ll)b - 1) <= _size); return comb(a - b * (c - 1) - 1, b - 1); } // O(min(b, a - b)) T _comb(ll a, ll b) const { if(a < b || b < 0) return 0; T res = 1; b = min(b, a - b); assert(b <= _size); for(int i = a; i > a - b; --i) res *= i; return res * ifact[b]; } // O(b) T _perm(ll a, ll b) const { if(a < b || b < 0) return 0; T res = 1; for(int i = a; i > a - b; --i) res *= i; return res; } // O(b) T _ban(int a, int b, int c = 1) const { return _comb(a - 1ll * b * (c - 1) - 1, b - 1); } // O(log a) T lucas(ll a, ll b) const { return (a >= b && b >= 0) ? (lucas(a / p, b / p) * comb(a % p, b % p)) : (0); } }; // Combinatorics<Mod> F(); ``` # 高精度 [Source](https://www.luogu.com/article/p6un33cl) ```cpp /* BigInteger.h (Version 2.4.2) stripe-python https://www.luogu.com.cn/user/928879 */ #ifndef BIGINTEGER_H #define BIGINTEGER_H class ZeroDivisionError : public std::exception { public: const char* what() const throw() {return "BigInteger::divmod";} }; class FFTLimitExceededError : public std::exception { public: const char* what() const throw() {return "BigInteger::fft_mul";} }; class BigInteger { protected: using digit_t = long long; static constexpr int WIDTH = 8; static constexpr digit_t BASE = 1e8; static constexpr long long FFT_LIMIT = 512; static constexpr long long NEWTON_LIMIT = 512; static constexpr long long NEWTON_MIN_LEVEL = 16; digit_t* digits; int capacity, size; bool flag; inline void push(const digit_t&); inline void pop(); inline int compare(const BigInteger&) const; static inline BigInteger fft_mul(const BigInteger&, const BigInteger&); inline BigInteger move_l(int) const; inline BigInteger move_r(int) const; BigInteger newton_inv(int) const; inline std::pair<BigInteger, BigInteger> newton_div(const BigInteger&) const; template <class F> inline static BigInteger binary_op_helper(const BigInteger&, const BigInteger&, const F&); public: inline void reserve(const int&); protected: inline void resize(const int&); public: BigInteger() : digits(nullptr), flag(true) {*this = 0;} BigInteger(const BigInteger& x) : digits(nullptr) {*this = x;} BigInteger(const long long& x) : digits(nullptr) {*this = x;} BigInteger(const std::string& s) : digits(nullptr) {*this = s;} BigInteger(const std::vector<bool>& b) : digits(nullptr) {*this = b;} template <class BoolIt> BigInteger(const BoolIt& begin, const BoolIt& end) : digits(nullptr) {*this = std::vector<bool>(begin, end);} BigInteger& operator= (const BigInteger&); BigInteger& operator= (const long long&); BigInteger& operator= (const std::string&); BigInteger& operator= (const std::vector<bool>&); void clear(); ~BigInteger() {clear();} friend std::ostream& operator<< (std::ostream& out, const BigInteger& x) { if (!x.flag) out << '-'; out << (long long) x.digits[x.size]; for (int i = x.size - 1; i >= 1; i--) out << std::setw(WIDTH) << std::setfill('0') << (long long) x.digits[i]; return out; } friend std::istream& operator>> (std::istream& in, BigInteger& x) { std::string s; in >> s; x = s; return in; } std::string to_string() const; long long to_long_long() const; std::vector<bool> to_binary() const; BigInteger operator- () const; BigInteger abs() const; bool operator== (const BigInteger&) const; #if __cplusplus >= 202002L auto operator<=> (const BigInteger&) const; #else bool operator< (const BigInteger&) const; bool operator> (const BigInteger&) const; bool operator!= (const BigInteger&) const; bool operator<= (const BigInteger&) const; bool operator>= (const BigInteger&) const; #endif //__cplusplus >= 202002L BigInteger div2() const; std::pair<BigInteger, BigInteger> divmod(const BigInteger&, bool = false) const; BigInteger operator+ (const BigInteger&) const; BigInteger operator- (const BigInteger&) const; BigInteger operator* (const int&) const; BigInteger operator* (const BigInteger&) const; BigInteger operator/ (const long long&) const; BigInteger operator/ (const BigInteger&) const; BigInteger operator% (const long long&) const; BigInteger operator% (const BigInteger&) const; BigInteger pow(const long long&) const; BigInteger pow(const long long&, const BigInteger&) const; BigInteger root(const long long& = 2) const; BigInteger gcd(const BigInteger&) const; BigInteger lcm(const BigInteger&) const; BigInteger& operator+= (const BigInteger&); BigInteger& operator-= (const BigInteger&); BigInteger& operator*= (int); BigInteger& operator*= (const BigInteger&); BigInteger& operator/= (const long long&); BigInteger& operator/= (const BigInteger&); BigInteger& operator%= (const long long&); BigInteger& operator%= (const BigInteger&); BigInteger operator<< (const long long&); BigInteger operator>> (const long long&); BigInteger& operator<<= (const long long&); BigInteger& operator>>= (const long long&); BigInteger operator& (const BigInteger&); BigInteger operator| (const BigInteger&); BigInteger operator^ (const BigInteger&); BigInteger& operator&= (const BigInteger&); BigInteger& operator|= (const BigInteger&); BigInteger& operator^= (const BigInteger&); BigInteger& operator++ (); BigInteger operator++ (int); BigInteger& operator-- (); BigInteger operator-- (int); }; inline void BigInteger::push(const digit_t& val) { if (size == capacity) { int new_capacity = 0; if (capacity < 1000) new_capacity = capacity << 1; else new_capacity = (capacity >> 1) * 3; if (new_capacity < 0) new_capacity = INT_MAX; digit_t* new_digits = new digit_t[new_capacity + 1]; std::memcpy(new_digits, digits, sizeof(long long) * (capacity + 1)); delete[] digits; digits = new_digits, capacity = new_capacity; } digits[++size] = val; } inline void BigInteger::pop() {digits[size--] = 0;} inline int BigInteger::compare(const BigInteger& x) const { if (flag && !x.flag) return 1; if (!flag && x.flag) return -1; int sgn = (flag && x.flag ? 1 : -1); if (size > x.size) return sgn; if (size < x.size) return -sgn; for (int i = size; i >= 1; i--) { if (digits[i] > x.digits[i]) return sgn; if (digits[i] < x.digits[i]) return -sgn; } return 0; } inline void BigInteger::reserve(const int& sz) { if (sz < 0) return; if (digits != nullptr) delete[] digits; capacity = sz, size = 0; digits = new digit_t[sz + 1]; std::memset(digits, 0, sizeof(digit_t) * (sz + 1)); } inline void BigInteger::resize(const int& sz) {reserve(sz), size = sz;} BigInteger& BigInteger::operator= (const BigInteger& x) { reserve(x.size + 1); flag = x.flag, size = x.size; std::memcpy(digits, x.digits, sizeof(digit_t) * (x.size + 1)); return *this; } BigInteger& BigInteger::operator= (const long long& x) { flag = (x >= 0), reserve(4); if (x == 0) return size = 1, digits[1] = 0, *this; if (x == LLONG_MIN) return *this = "-9223372036854775808"; long long n = std::abs(x); do {push(n % BASE), n /= BASE;} while (n); return *this; } BigInteger& BigInteger::operator= (const std::string& s) { flag = true, reserve(s.size() / WIDTH + 1); if (s.empty() || s == "-") return *this = 0; int i = 0; if (s[0] == '-') flag = false, i++; for (int j = s.size() - 1; j >= i; j -= WIDTH) { int start = std::max(i, j - WIDTH + 1), len = j - start + 1; push(std::stoll(s.substr(start, len))); } return *this; } BigInteger& BigInteger::operator= (const std::vector<bool>& b) { *this = 0; if (b.empty() || (b.size() == 1 && b[0] == 0)) return *this; BigInteger pow2 = 1; for (int i = b.size() - 1; i >= 0; i--, pow2 += pow2) if (b[i]) *this += pow2; return *this; } void BigInteger::clear() {if (digits != nullptr) delete[] digits, digits = nullptr;} std::string BigInteger::to_string() const {std::stringstream ss; ss << *this; return ss.str();} long long BigInteger::to_long_long() const {return std::stoll(to_string());} std::vector<bool> BigInteger::to_binary() const { if (*this == 0) return {0}; std::vector<bool> res; for (BigInteger x = *this; x != 0; x = x.div2()) res.emplace_back(x.digits[1] & 1); std::reverse(res.begin(), res.end()); return res; }; BigInteger BigInteger::operator- () const { if (*this == 0) return 0; BigInteger res = *this; res.flag = !flag; return res; } BigInteger BigInteger::abs() const {BigInteger res = *this; res.flag = true; return res;} bool BigInteger::operator== (const BigInteger& x) const {return compare(x) == 0;} #if __cplusplus >= 202002L auto BigInteger::operator<=> (const BigInteger& x) const {return compare(x);} #else bool BigInteger::operator< (const BigInteger& x) const {return compare(x) < 0;} bool BigInteger::operator> (const BigInteger& x) const {return compare(x) > 0;} bool BigInteger::operator!= (const BigInteger& x) const {return compare(x) != 0;} bool BigInteger::operator<= (const BigInteger& x) const {return compare(x) <= 0;} bool BigInteger::operator>= (const BigInteger& x) const {return compare(x) >= 0;} #endif //__cplusplus >= 202002L BigInteger BigInteger::operator+ (const BigInteger& x) const { if (!x.flag) return *this - x.abs(); if (!flag) return x - abs(); BigInteger res; res.flag = !(flag ^ x.flag); int n = std::max(size, x.size) + 1; res.reserve(n); digit_t carry = 0; for (int i = 1; i <= n; i++) { digit_t d1 = i <= size ? digits[i] : 0, d2 = i <= x.size ? x.digits[i] : 0; res.push(d1 + d2 + carry); carry = res.digits[i] / BASE; res.digits[i] %= BASE; } while (res.size > 1 && res.digits[res.size] == 0) res.pop(); return res; } BigInteger BigInteger::operator- (const BigInteger& x) const { if (!x.flag) return *this + x.abs(); if (!flag) return -(abs() + x); BigInteger res; if (*this < x) res.flag = false; digit_t carry = 0; int n = std::max(size, x.size); res.reserve(n); for (int i = 1; i <= n; i++) { digit_t d1 = i <= size ? digits[i] : 0, d2 = i <= x.size ? x.digits[i] : 0; if (res.flag) res.push(d1 - d2 - carry); else res.push(d2 - d1 - carry); if (res.digits[i] < 0) res.digits[i] += BASE, carry = 1; else carry = 0; } while (res.size > 1 && res.digits[res.size] == 0) res.pop(); return res; } namespace __FFT { constexpr long long FFT_BASE = 1e4; constexpr double PI2 = 6.283185307179586231995927; constexpr double PI6 = 18.84955592153875869598778; constexpr int RECALC_WIDTH = 10; constexpr int RECALC_BASE = (1 << RECALC_WIDTH) - 1; struct complex { double real, imag; complex(double x = 0.0, double y = 0.0) : real(x), imag(y) {} complex operator+ (const complex& other) const {return complex(real + other.real, imag + other.imag);} complex operator- (const complex& other) const {return complex(real - other.real, imag - other.imag);} complex operator* (const complex& other) const {return complex(real * other.real - imag * other.imag, real * other.imag + other.real * imag);} complex& operator+= (const complex& other) {return real += other.real, imag += other.imag, *this;} complex& operator-= (const complex& other) {return real -= other.real, imag -= other.imag, *this;} complex& operator*= (const complex& other) {return *this = *this * other;} }; complex* arr = nullptr; inline void init(int n) { if (arr != nullptr) delete[] arr, arr = nullptr; arr = new complex[n + 1]; } template <const int n> inline void fft(complex* a) { const int n2 = n >> 1, n4 = n >> 2; complex w(1.0, 0.0), w3(1.0, 0.0); const complex wn(std::cos(PI2 / n), std::sin(PI2 / n)), wn3(std::cos(PI6 / n), std::sin(PI6 / n)); for (int i = 0; i < n4; i++, w *= wn, w3 *= wn3) { if (!(i & RECALC_BASE)) w = complex(std::cos(PI2 * i / n), std::sin(PI2 * i / n)), w3 = w * w * w; complex x = a[i] - a[i + n2], y = a[i + n4] - a[i + n2 + n4]; y = complex(y.imag, -y.real); a[i] += a[i + n2], a[i + n4] += a[i + n2 + n4]; a[i + n2] = (x - y) * w, a[i + n2 + n4] = (x + y) * w3; } fft<n2>(a), fft<n4>(a + n2), fft<n4>(a + n2 + n4); } template <> inline void fft<1>(complex* a) {} template <> inline void fft<0>(complex* a) {} template <> inline void fft<2>(complex* a) { complex x = a[0], y = a[1]; a[0] += y, a[1] = x - y; } template <> inline void fft<4>(complex* a) { complex a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3]; complex x = a0 - a2, y = a1 - a3; y = complex(y.imag, -y.real); a[0] += a2, a[1] += a3, a[2] = x - y, a[3] = x + y; fft<2>(a); } template <const int n> inline void ifft(complex* a) { const int n2 = n >> 1, n4 = n >> 2; ifft<n2>(a), ifft<n4>(a + n2), ifft<n4>(a + n2 + n4); complex w(1.0, 0.0), w3(1.0, 0.0); const complex wn(std::cos(PI2 / n), -std::sin(PI2 / n)), wn3(std::cos(PI6 / n), -std::sin(PI6 / n)); for (int i = 0; i < n4; i++, w *= wn, w3 *= wn3) { if (!(i & RECALC_BASE)) w = complex(std::cos(PI2 * i / n), -std::sin(PI2 * i / n)), w3 = w * w * w; complex p = w * a[i + n2], q = w3 * a[i + n2 + n4]; complex x = a[i], y = p + q, x1 = a[i + n4], y1 = p - q; y1 = complex(y1.imag, -y1.real); a[i] += y, a[i + n4] += y1, a[i + n2] = x - y, a[i + n2 + n4] = x1 - y1; } } template <> inline void ifft<1>(complex* a) {} template <> inline void ifft<0>(complex* a) {} template <> inline void ifft<2>(complex* a) { complex x = a[0], y = a[1]; a[0] += y, a[1] = x - y; } template <> inline void ifft<4>(complex* a) { ifft<2>(a); complex p = a[2], q = a[3]; complex x = a[0], y = p + q, x1 = a[1], y1 = p - q; y1 = complex(y1.imag, -y1.real); a[0] += y, a[1] += y1, a[2] = x - y, a[3] = x1 - y1; } inline void dft(complex* a, int n) { if (n <= 1) return; switch (n) { case 1 << 2: fft<1 << 2>(a); break; case 1 << 3: fft<1 << 3>(a); break; case 1 << 4: fft<1 << 4>(a); break; case 1 << 5: fft<1 << 5>(a); break; case 1 << 6: fft<1 << 6>(a); break; case 1 << 7: fft<1 << 7>(a); break; case 1 << 8: fft<1 << 8>(a); break; case 1 << 9: fft<1 << 9>(a); break; case 1 << 10: fft<1 << 10>(a); break; case 1 << 11: fft<1 << 11>(a); break; case 1 << 12: fft<1 << 12>(a); break; case 1 << 13: fft<1 << 13>(a); break; case 1 << 14: fft<1 << 14>(a); break; case 1 << 15: fft<1 << 15>(a); break; case 1 << 16: fft<1 << 16>(a); break; case 1 << 17: fft<1 << 17>(a); break; case 1 << 18: fft<1 << 18>(a); break; case 1 << 19: fft<1 << 19>(a); break; case 1 << 20: fft<1 << 20>(a); break; case 1 << 21: fft<1 << 21>(a); break; case 1 << 22: fft<1 << 22>(a); break; case 1 << 23: fft<1 << 23>(a); break; case 1 << 24: fft<1 << 24>(a); break; case 1 << 25: fft<1 << 25>(a); break; case 1 << 26: fft<1 << 26>(a); break; case 1 << 27: fft<1 << 27>(a); break; case 1 << 28: fft<1 << 28>(a); break; case 1 << 29: fft<1 << 29>(a); break; case 1 << 30: fft<1 << 30>(a); break; case 1 << 31: fft<1 << 31>(a); break; throw FFTLimitExceededError(); } } inline void idft(complex* a, int n) { if (n <= 1) return; switch (n) { case 1 << 2: ifft<1 << 2>(a); break; case 1 << 3: ifft<1 << 3>(a); break; case 1 << 4: ifft<1 << 4>(a); break; case 1 << 5: ifft<1 << 5>(a); break; case 1 << 6: ifft<1 << 6>(a); break; case 1 << 7: ifft<1 << 7>(a); break; case 1 << 8: ifft<1 << 8>(a); break; case 1 << 9: ifft<1 << 9>(a); break; case 1 << 10: ifft<1 << 10>(a); break; case 1 << 11: ifft<1 << 11>(a); break; case 1 << 12: ifft<1 << 12>(a); break; case 1 << 13: ifft<1 << 13>(a); break; case 1 << 14: ifft<1 << 14>(a); break; case 1 << 15: ifft<1 << 15>(a); break; case 1 << 16: ifft<1 << 16>(a); break; case 1 << 17: ifft<1 << 17>(a); break; case 1 << 18: ifft<1 << 18>(a); break; case 1 << 19: ifft<1 << 19>(a); break; case 1 << 20: ifft<1 << 20>(a); break; case 1 << 21: ifft<1 << 21>(a); break; case 1 << 22: ifft<1 << 22>(a); break; case 1 << 23: ifft<1 << 23>(a); break; case 1 << 24: ifft<1 << 24>(a); break; case 1 << 25: ifft<1 << 25>(a); break; case 1 << 26: ifft<1 << 26>(a); break; case 1 << 27: ifft<1 << 27>(a); break; case 1 << 28: ifft<1 << 28>(a); break; case 1 << 29: ifft<1 << 29>(a); break; case 1 << 30: ifft<1 << 30>(a); break; case 1 << 31: ifft<1 << 31>(a); break; throw FFTLimitExceededError(); } } } BigInteger BigInteger::fft_mul(const BigInteger& a, const BigInteger& b) { static_assert(__FFT::FFT_BASE * __FFT::FFT_BASE == BASE); int least = (a.size + b.size) << 1, lim = 1 << std::__lg(least); if (lim < least) lim <<= 1; __FFT::init(lim); using __FFT::arr; for (int i = 0; i < a.size; i++) { arr[i << 1].real = a.digits[i + 1] % 10000; arr[i << 1 | 1].real = a.digits[i + 1] / 10000 % 10000; } for (int i = 0; i < b.size; i++) { arr[i << 1].imag = b.digits[i + 1] % 10000; arr[i << 1 | 1].imag = b.digits[i + 1] / 10000 % 10000; } __FFT::dft(arr, lim); for (int i = 0; i < lim; i++) arr[i] *= arr[i]; __FFT::idft(arr, lim); BigInteger res; res.resize(a.size + b.size + 1); digit_t carry = 0; double inv = 0.5 / lim; for (int i = 0; i <= a.size + b.size; i++) { carry += (digit_t)(arr[i << 1].imag * inv + 0.5); carry += (digit_t)(arr[i << 1 | 1].imag * inv + 0.5) * 10000LL; res.digits[i + 1] += carry % BASE, carry /= BASE; } while (res.size > 1 && res.digits[res.size] == 0) res.pop(); return res; } BigInteger BigInteger::operator* (const BigInteger& x) const { BigInteger zero = 0; if (*this == zero || x == zero) return zero; int n = size, m = x.size; long long lim = 1LL * n * m; if (lim >= FFT_LIMIT) { BigInteger res = fft_mul(*this, x); res.flag = !(flag ^ x.flag); return res; } BigInteger res; res.flag = !(flag ^ x.flag); res.resize(n + m + 2); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { res.digits[i + j - 1] += digits[i] * x.digits[j]; res.digits[i + j] += res.digits[i + j - 1] / BASE; res.digits[i + j - 1] %= BASE; } } for (int i = 1; i <= n + m + 1; i++) { res.digits[i + 1] += res.digits[i] / BASE; res.digits[i] %= BASE; } while (res.size > 1 && res.digits[res.size] == 0) res.pop(); return res; } BigInteger& BigInteger::operator*= (int x) { if (x == 0 || *this == 0) return *this = 0; if (x < 0) flag = !flag, x = -x; digit_t carry = 0; for (int i = 1; i <= size || carry; i++) { if (i > size) push(0); digit_t cur = digits[i] * x + carry; carry = cur / BigInteger::BASE; digits[i] = cur % BigInteger::BASE; } while (size > 1 && digits[size] == 0) pop(); return *this; } BigInteger BigInteger::operator* (const int& x) const {BigInteger t = *this; return t *= x;} BigInteger BigInteger::div2() const { BigInteger res = *this; for (int i = size; i >= 1; i--) { if ((res.digits[i] & 1) && (i > 1)) res.digits[i - 1] += BASE; res.digits[i] >>= 1; } while (res.size > 1 && res.digits[res.size] == 0) res.pop(); return res; } BigInteger BigInteger::operator/ (const long long& x) const { if (x == 0) throw -1; if (*this == 0) return 0; if (x == 2) return div2(); if (x == -2) {BigInteger res = div2(); res.flag = !res.flag; return res;} BigInteger res; res.flag = !(flag ^ (x >= 0)); digit_t cur = 0, div = std::abs(x); res.resize(size); for (int i = size; i >= 1; i--) { cur = cur * BASE + digits[i]; res.digits[i] = res.flag ? (cur / div) : (-cur / -div); cur %= div; } while (res.size > 1 && res.digits[res.size] == 0) res.pop(); return res; } inline BigInteger BigInteger::move_r(int d) const { if (*this == 0 || d >= size) return 0; if (d == 0) return *this; BigInteger res; res.reserve(size - d + 1); for (int i = d + 1; i <= size; i++) res.push(digits[i]); return res; } inline BigInteger BigInteger::move_l(int d) const { if (*this == 0) return 0; if (d == 0) return *this; BigInteger res; res.reserve(size + d + 1); for (int i = 1; i <= d; i++) res.push(0); for (int i = 1; i <= size; i++) res.push(digits[i]); return res; } BigInteger BigInteger::newton_inv(int n) const { if (*this == 0) throw ZeroDivisionError(); if (std::min(size, n - size) <= NEWTON_MIN_LEVEL) { BigInteger a; a.resize(n + 1); std::memset(a.digits, 0, sizeof(digit_t) * a.size); a.digits[n + 1] = 1; return a.divmod(*this, true).first; } int k = (n - size + 5) >> 1, k2 = k > size ? 0 : size - k; BigInteger x = move_r(k2); int n2 = k + x.size; BigInteger y = x.newton_inv(n2), a = y + y, b = (*this) * y * y; return a.move_l(n - n2 - k2) - b.move_r(2 * (n2 + k2) - n) - 1; } std::pair<BigInteger, BigInteger> BigInteger::newton_div(const BigInteger& x) const { int k = size - x.size + 5, k2 = k > x.size ? 0 : x.size - k; BigInteger x2 = x.move_r(k2); if (k2 != 0) x2 += 1; int n2 = k + x2.size; BigInteger u = (*this) * x2.newton_inv(n2); BigInteger q = u.move_r(n2 + k2), r = (*this) - q * x; while (r >= x) q += 1, r -= x; return std::make_pair(q, r); } std::pair<BigInteger, BigInteger> BigInteger::divmod(const BigInteger& x, bool dis_newton) const { static const int base = BigInteger::BASE; BigInteger a = abs(), b = x.abs(); if (b == 0) throw ZeroDivisionError(); if (a < b) return std::make_pair(0, flag ? a : -a); if (!dis_newton && size > NEWTON_LIMIT) return newton_div(x); int t = base / (x.digits[x.size] + 1); a *= t, b *= t; int n = a.size, m = b.size; BigInteger q = 0, r = 0; q.resize(n); for (int i = n; i >= 1; i--) { r *= base, r += a.digits[i]; digit_t d1 = m < r.size ? r.digits[m + 1] : 0, d2 = m - 1 < r.size ? r.digits[m] : 0; int d = (d1 * base + d2) / b.digits[m]; r -= b * d; while (!r.flag) r += b, d--; q.digits[i] = d; } q.flag = !(flag ^ x.flag), r.flag = flag; while (q.size > 1 && q.digits[q.size] == 0) q.pop(); return std::make_pair(q, r / t); } BigInteger BigInteger::operator/ (const BigInteger& x) const {return divmod(x).first;} BigInteger BigInteger::operator% (const long long& x) const { if (x == 2) return digits[1] & 1; if (x == 5) return digits[1] % 5; return *this - (*this / x * x); } BigInteger BigInteger::operator% (const BigInteger& x) const {return divmod(x).second;} BigInteger BigInteger::pow(const long long& x) const { BigInteger res = 1, a = *this; for (long long t = x; t != 0; t >>= 1) { if (t & 1) res *= a; a *= a; } return res; } BigInteger BigInteger::pow(const long long& x, const BigInteger& p) const { BigInteger res = 1, a = *this % p; for (long long t = x; t != 0; t >>= 1) { if (t & 1) res = res * a % p; a = a * a % p; } return res; } BigInteger BigInteger::root(const long long& m) const { if (*this == 0 || m == 1) return *this; static constexpr long long base = BigInteger::BASE; BigInteger n = *this, t = base, x = std::min(n, t.move_l((n.size + m) / m)); int l = 0, r = base - 1; while (l < r) { int mid = (l + r) >> 1; x.digits[x.size] = mid; if (x.pow(m) <= n) l = mid + 1; else r = mid; } x.digits[x.size] = l; while (x.size > 1 && x.digits[x.size] == 0) x.pop(); BigInteger x2 = (x * (m - 1) + n / x.pow(m - 1)) / m; while (x2 < x) std::swap(x2, x), x2 = (x * (m - 1) + n / x.pow(m - 1)) / m; return x; } BigInteger BigInteger::gcd(const BigInteger& x) const { BigInteger a = *this, b = x; if (a < b) std::swap(a, b); if (b == 0) return a; int t = 0; while (a % 2 == 0 && b % 2 == 0) a = a.div2(), b = b.div2(), t++; while (b > 0) { if (a % 2 == 0) a = a.div2(); else if (b % 2 == 0) b = b.div2(); else a -= b; if (a < b) std::swap(a, b); } while (t--) a += a; return a; } BigInteger BigInteger::lcm(const BigInteger& x) const {return *this / gcd(x) * x;} BigInteger& BigInteger::operator+= (const BigInteger& x) {return *this = *this + x;} BigInteger& BigInteger::operator-= (const BigInteger& x) {return *this = *this - x;} BigInteger& BigInteger::operator*= (const BigInteger& x) {return *this = *this * x;} BigInteger& BigInteger::operator/= (const long long& x) {return *this = *this / x;} BigInteger& BigInteger::operator/= (const BigInteger& x) {return *this = *this / x;} BigInteger& BigInteger::operator%= (const long long& x) {return *this = *this / x;} BigInteger& BigInteger::operator%= (const BigInteger& x) {return *this = *this % x;} BigInteger BigInteger::operator<< (const long long& x) { if (x <= 0) return *this; BigInteger res = *this; for (long long i = 1; i <= x; i++) res += res; return res; } BigInteger BigInteger::operator>> (const long long& x) { if (x <= 0) return *this; BigInteger res = *this; for (long long i = 1; i <= x; i++) res = res.div2(); return res; } BigInteger& BigInteger::operator<<= (const long long& x) {return *this = *this << x;} BigInteger& BigInteger::operator>>= (const long long& x) {return *this = *this >> x;} template <class F> inline BigInteger BigInteger::binary_op_helper(const BigInteger& x, const BigInteger& y, const F& func) { auto to_bin = [](BigInteger x) -> std::vector<bool> { if (x == 0) return {0}; std::vector<bool> res; for (; x != 0; x = x.div2()) res.emplace_back(x.digits[1] & 1); return res; }; std::vector<bool> a = to_bin(x), b = to_bin(y); int n = a.size(), m = b.size(), lim = std::max(n, m); std::vector<bool> res(lim, 0); for (int i = lim - 1; i >= 0; i--) res[i] = func(i < n ? a[i] : 0, i < m ? b[i] : 0); std::reverse(res.begin(), res.end()); return res; } BigInteger BigInteger::operator& (const BigInteger& x) {return binary_op_helper(*this, x, [](bool a, bool b) -> bool {return a & b;});} BigInteger BigInteger::operator| (const BigInteger& x) {return binary_op_helper(*this, x, [](bool a, bool b) -> bool {return a | b;});} BigInteger BigInteger::operator^ (const BigInteger& x) {return binary_op_helper(*this, x, [](bool a, bool b) -> bool {return a ^ b;});} BigInteger& BigInteger::operator&= (const BigInteger& x) {return *this = *this & x;} BigInteger& BigInteger::operator|= (const BigInteger& x) {return *this = *this | x;} BigInteger& BigInteger::operator^= (const BigInteger& x) {return *this = *this ^ x;} BigInteger& BigInteger::operator++ () {return *this += 1;} BigInteger BigInteger::operator++ (int) {BigInteger t = *this; return *this += 1, t;} BigInteger& BigInteger::operator-- () {return *this -= 1;} BigInteger BigInteger::operator-- (int) {BigInteger t = *this; return *this -= 1, t;} #endif //BIGINTEGER_H ```