模板
高精度
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指定范围忽视掉