模板

Posted on Oct 21, 2025

高精度

code
struct INT {
    static const int base = 1000000000; // 1e9
    static const int base_digits = 9;
    vector<int> a; // little-endian digits
    int sign; // 1 or -1

    INT(): sign(1) {}
    INT(long long v) { *this = v; }
    INT& operator=(long long v) {
        sign = 1;
        if (v < 0) sign = -1, v = -v;
        a.clear();
        while (v) {
            a.push_back(v % base);
            v /= base;
        }
        return *this;
    }
    INT(const string &s) { read(s); }

    INT& read(const string &s) {
        sign = 1;
        a.clear();
        int pos = 0;
        while (pos < (int)s.size() && isspace(s[pos])) ++pos;
        if (pos < (int)s.size() && (s[pos] == '-' || s[pos] == '+')) {
            if (s[pos] == '-') sign = -1;
            ++pos;
        }
        for (int i = s.size() - 1; i >= pos; i -= base_digits) {
            int x = 0;
            int l = max(pos, i - base_digits + 1);
            for (int j = l; j <= i; ++j) x = x * 10 + (s[j] - '0');
            a.push_back(x);
        }
        trim();
        return *this;
    }

    string toString() const {
        if (isZero()) return "0";
        string s = sign == -1 ? "-" : "";
        int n = a.size();
        s += to_string(a.empty() ? 0 : a.back());
        for (int i = n - 2; i >= 0; --i) {
            string t = to_string(a[i]);
            s += string(base_digits - t.length(), '0') + t;
        }
        return s;
    }

    bool isZero() const { return a.empty(); }

    void trim() {
        while (!a.empty() && a.back() == 0) a.pop_back();
        if (a.empty()) sign = 1;
    }

    // absolute compare: returns -1,0,1 for |this| ? |v|
    int cmpAbs(const INT &v) const {
        if (a.size() != v.a.size())
            return a.size() < v.a.size() ? -1 : 1;
        for (int i = (int)a.size() - 1; i >= 0; --i)
            if (a[i] != v.a[i]) return a[i] < v.a[i] ? -1 : 1;
        return 0;
    }

    int compare(const INT &v) const {
        if (sign != v.sign) return sign < v.sign ? -1 : 1;
        int c = cmpAbs(v);
        return sign == 1 ? c : -c;
    }

    // operators
    bool operator<(const INT &v) const { return compare(v) < 0; }
    bool operator>(const INT &v) const { return compare(v) > 0; }
    bool operator<=(const INT &v) const { return compare(v) <= 0; }
    bool operator>=(const INT &v) const { return compare(v) >= 0; }
    bool operator==(const INT &v) const { return sign == v.sign && a == v.a; }
    bool operator!=(const INT &v) const { return !(*this == v); }

    // abs addition (|this| + |v|)
    static INT addAbs(const INT &x, const INT &y) {
        INT res;
        long long carry = 0;
        size_t n = max(x.a.size(), y.a.size());
        res.a.resize(n);
        for (size_t i = 0; i < n; ++i) {
            long long sum = carry;
            if (i < x.a.size()) sum += x.a[i];
            if (i < y.a.size()) sum += y.a[i];
            res.a[i] = int(sum % base);
            carry = sum / base;
        }
        if (carry) res.a.push_back((int)carry);
        return res;
    }

    // abs subtraction (|x| - |y|), assume |x| >= |y|
    static INT subAbs(const INT &x, const INT &y) {
        INT res;
        res.a.resize(x.a.size());
        long long carry = 0;
        for (size_t i = 0; i < x.a.size(); ++i) {
            long long cur = x.a[i] - carry - (i < y.a.size() ? y.a[i] : 0);
            carry = 0;
            if (cur < 0) cur += base, carry = 1;
            res.a[i] = (int)cur;
        }
        res.trim();
        return res;
    }

    INT operator-() const {
        INT r = *this;
        if (!isZero()) r.sign = -sign;
        return r;
    }

    INT operator+(const INT &v) const {
        if (sign == v.sign) {
            INT res = addAbs(*this, v);
            res.sign = sign;
            return res;
        }
        if (cmpAbs(v) >= 0) {
            INT res = subAbs(*this, v); res.sign = sign; return res;
        } else {
            INT res = subAbs(v, *this); res.sign = v.sign; return res;
        }
    }

    INT operator-(const INT &v) const {
        if (sign != v.sign) {
            INT res = addAbs(*this, v); res.sign = sign; return res;
        }
        if (cmpAbs(v) >= 0) {
            INT res = subAbs(*this, v); res.sign = sign; return res;
        } else {
            INT res = subAbs(v, *this); res.sign = -sign; return res;
        }
    }

    INT operator*(const INT &v) const {
        if (isZero() || v.isZero()) return INT(0);
        INT res;
        res.sign = sign * v.sign;
        res.a.assign(a.size() + v.a.size(), 0);
        for (size_t i = 0; i < a.size(); ++i) {
            long long carry = 0;
            for (size_t j = 0; j < v.a.size() || carry; ++j) {
                long long cur = res.a[i + j] + carry + 1LL * a[i] * (j < v.a.size() ? v.a[j] : 0);
                res.a[i + j] = int(cur % base);
                carry = cur / base;
            }
        }
        res.trim();
        return res;
    }

    // divmod: returns pair(quotient, remainder), remainder has same sign as *this and 0<=rem<|v|
    static pair<INT, INT> divmod(const INT &a1, const INT &b1) {
        int norm = base / ( (long long)b1.a.back() + 1 );
        INT a = a1.absMulInt(norm);
        INT b = b1.absMulInt(norm);
        INT q; q.sign = a1.sign * b1.sign;
        INT r; r.sign = 1;
        q.a.assign(a.a.size(), 0);
        for (int i = (int)a.a.size() - 1; i >= 0; --i) {
            r.a.insert(r.a.begin(), a.a[i]);
            if (!r.a.back()) r.a.pop_back(); // keep trim later
            // estimate quotient digit
            long long s1 = r.a.size() > b.a.size() ? r.a[b.a.size()] : 0;
            long long s2 = r.a.size() > b.a.size() - 1 ? r.a[b.a.size() - 1] : 0;
            long long d = ( (s1 * base) + s2 ) / b.a.back();
            if (d >= base) d = base - 1;
            // multiply and subtract
            INT bd = b.absMulInt(d);
            while (r.cmpAbs(bd) < 0) { --d; bd = b.absMulInt(d); }
            r = subAbs(r, bd);
            q.a[i] = (int)d;
        }
        q.trim();
        // remainder: divide back by norm
        r = r.divInt(norm);
        q.sign = a1.sign * b1.sign;
        if (q.isZero()) q.sign = 1;
        if (r.isZero()) r.sign = 1; else r.sign = a1.sign;
        return {q, r};
    }

    // divide by int, returns quotient
    INT divInt(int v) const {
        INT res = *this;
        long long carry = 0;
        for (int i = (int)res.a.size() - 1; i >= 0; --i) {
            long long cur = res.a[i] + carry * base;
            res.a[i] = int(cur / v);
            carry = cur % v;
        }
        res.trim();
        return res;
    }

    // multiply abs by int (non-negative)
    INT absMulInt(long long m) const {
        if (isZero() || m == 0) return INT(0);
        INT res;
        res.sign = 1;
        long long carry = 0;
        res.a.resize(a.size());
        for (size_t i = 0; i < a.size(); ++i) {
            long long cur = carry + 1LL * a[i] * m;
            res.a[i] = int(cur % base);
            carry = cur / base;
        }
        while (carry) {
            res.a.push_back(int(carry % base));
            carry /= base;
        }
        res.trim();
        return res;
    }

    // divide by small int (positive) in-place (returns remainder)
    int divmodInt(int v) {
        long long carry = 0;
        for (int i = (int)a.size() - 1; i >= 0; --i) {
            long long cur = a[i] + carry * base;
            a[i] = int(cur / v);
            carry = cur % v;
        }
        trim();
        return (int)carry;
    }

    // helper: absolute division by int (used in divmod normalization)
    INT divInt(long long v) const {
        INT res;
        res.sign = sign;
        res.a.resize(a.size());
        long long carry = 0;
        for (int i = (int)a.size() - 1; i >= 0; --i) {
            long long cur = a[i] + carry * base;
            res.a[i] = int(cur / v);
            carry = cur % v;
        }
        res.trim();
        return res;
    }

    // public divide and mod
    INT operator/(const INT &v) const {
        return divmod(*this, v).first;
    }
    INT operator%(const INT &v) const {
        return divmod(*this, v).second;
    }

    // convenience with long long
    INT operator+(long long v) const { return *this + INT(v); }
    INT operator-(long long v) const { return *this - INT(v); }
    INT operator*(long long v) const { return *this * INT(v); }
    INT operator/(long long v) const { return *this / INT(v); }
    INT operator%(long long v) const { return *this % INT(v); }

    // abs multiply by base power (not needed often)
    void shiftDigits(int cnt) {
        if (isZero() || cnt == 0) return;
        a.insert(a.begin(), cnt, 0);
    }
};

// IO helpers
ostream& operator<<(ostream &os, const INT &v) { return os << v.toString(); }
istream& operator>>(istream &is, INT &v) { string s; is >> s; v.read(s); return is; }

离散化

code
vector<int> a(n+1),b(n+1);
for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i];
sort(b.begin()+1,b.end());
auto end=unique(b.begin()+1,b.end());
for(int i=1;i<+n;i++)
  a[i]=lower_bound(b.begin()+1,end,a[i]);

end为unique后序列的(末尾迭代器+1),之后还储存着无用元素
可用lower_bound指定范围忽视掉