diff --git a/algorithms/math/big_integer.cpp b/algorithms/math/big_integer.cpp index 28851c8649c7349dcda5043b4f13b1862f4e1cbe..f88c09f0d43e6a46947257b07523f79d4f69de14 100644 --- a/algorithms/math/big_integer.cpp +++ b/algorithms/math/big_integer.cpp @@ -1,100 +1,231 @@ /// Big Integer /// /// Space: O(n) +/// +/// Status: Tested (KRAKOVIA) +/// Caution: Just use python. const int base = 1000000000; const int base_d = 9; struct BigInt { - int sign = 1; + int sign; vector<int> num; - BigInt() {} - BigInt(const string &x) { read(x); } + BigInt() : sign(1) {} + BigInt(ll x) { *this = x; } + BigInt(const string &s) { read(s); } + + void operator=(const BigInt &x) { + sign = x.sign; + num = x.num; + } + + void operator=(ll x) { + sign = 1; + if (x < 0) sign = -1, x = -x; + for (; x > 0; x /= base) + pb(x % base); + } BigInt operator+(const BigInt &x) const { if (sign != x.sign) return *this - (-x); - BigInt ans = x; + int carry = 0; - for (int i = 0; i < max(size(), x.size()) || carry; ++i) { - if (i == ans.size()) ans.push_back(0); + BigInt res = x; - if (i < size()) ans[i] += carry + num[i]; - else ans[i] += carry; + for (int i = 0; i < max(size(), x.size()) || carry; ++i) { + if (i == (int) res.size()) + res.push_back(0); - carry = ans[i] >= base; - if (carry) ans[i] -= base; + res[i] += carry + (i < size() ? num[i] : 0); + carry = res[i] >= base; + if (carry) res[i] -= base; } - return ans; + return res; } - BigInt operator-(const BigInt& x) const { - if (sign != x.sign) - return *this + (-x); - if (abs() < x.abs()) - return -(x - *this); + BigInt operator-(const BigInt &x) const { + if (sign != x.sign) return *this + (-x); + if (abs() < x.abs()) return -(x - *this); - BigInt ans = *this; int carry = 0; + BigInt res = *this; + for (int i = 0; i < x.size() || carry; ++i) { - if (i < x.size()) ans[i] -= carry + x[i]; - else ans[i] -= carry; + res[i] -= carry + (i < x.size() ? x[i] : 0); + carry = res[i] < 0; + if (carry) res[i] += base; + } + + res.trim(); + return res; + } + + void operator*=(int x) { + if (x < 0) sign = -sign, x = -x; + + int carry = 0; + for (int i = 0; i < size() || carry; ++i) { + if (i == size()) pb(0); + ll cur = num[i] * (ll) x + carry; - carry = ans[i] < 0; - if (carry) ans[i] += base; + carry = (int) (cur / base); + num[i] = (int) (cur % base); } - ans.trim(); - return ans; + trim(); } - // Removes leading zeros. - void trim() { - while (!num.empty() && num.back() == 0) - num.pop_back(); + BigInt operator*(int x) const { + BigInt res = *this; + res *= x; + return res; + } + + friend pair<BigInt, BigInt> divmod(const BigInt &a1, + const BigInt &b1) + { + int norm = base / (b1.back() + 1); + BigInt a = a1.abs() * norm; + BigInt b = b1.abs() * norm; + BigInt q, r; + q.resize(a.size()); + + for (int i = a.size() - 1; i >= 0; i--) { + r *= base; + r += a[i]; + + int s1 = r.size() <= b.size() ? 0 : r[b.size()]; + int s2 = r.size() <= b.size() - 1 ? 0 : r[b.size() - 1]; + int d = ((ll) base * s1 + s2) / b.back(); + + r -= b * d; + while (r < 0) r += b, --d; + q[i] = d; + } + + q.sign = a1.sign * b1.sign; + r.sign = a1.sign; + q.trim(); r.trim(); + + return make_pair(q, r / norm); + } + + BigInt operator/(const BigInt &x) const { + return divmod(*this, x).fi; + } + + BigInt operator%(const BigInt &x) const { + return divmod(*this, x).se; + } + + void operator/=(int x) { + if (x < 0) sign = -sign, x = -x; + + for (int i = size() - 1, rem = 0; i >= 0; --i) { + ll cur = num[i] + rem * (ll) base; + num[i] = (int) (cur / x); + rem = (int) (cur % x); + } + + trim(); + } + + BigInt operator/(int x) const { + BigInt res = *this; + res /= x; + return res; + } + + int operator%(int x) const { + if (x < 0) x = -x; + + int m = 0; + for (int i = size() - 1; i >= 0; --i) + m = (num[i] + m * (ll) base) % x; + + return m * sign; + } - if (num.empty()) - sign = 1; + void operator+=(const BigInt &x) { + *this = *this + x; + } + void operator-=(const BigInt &x) { + *this = *this - x; + } + void operator*=(const BigInt &x) { + *this = *this * x; + } + void operator/=(const BigInt &x) { + *this = *this / x; } - bool operator<(const BigInt &x) { + bool operator<(const BigInt &x) const { if (sign != x.sign) return sign < x.sign; - + if (size() != x.size()) - return (size() * sign) < (x.size() * x.sign); + return size() * sign < x.size() * x.sign; for (int i = size() - 1; i >= 0; i--) if (num[i] != x[i]) - return (num[i] * sign) < (x[i] * x.sign); + return num[i] * sign < x[i] * sign; return false; } - bool operator==(const BigInt &x) { - return !(*this < x) && !(x < *this); + bool operator>(const BigInt &x) const { + return x < *this; + } + bool operator<=(const BigInt &x) const { + return !(x < *this); + } + bool operator>=(const BigInt &x) const { + return !(*this < x); + } + bool operator==(const BigInt &x) const { + return !(*this < x) && !(x < *this); + } + bool operator!=(const BigInt &x) const { + return *this < x || x < *this; } - bool operator>(const BigInt &x) const { return (x < *this); } - bool operator<=(const BigInt &x) const { return !(x < *this); } - bool operator>=(const BigInt &x) const { return !(*this < x); } - bool operator!=(const BigInt &x) const { return !(*this == x); } + void trim() { + while (!empty() && !back()) pop_back(); + if (empty()) sign = 1; + } + bool is_zero() const { + return empty() || (size() == 1 && !num[0]); + } - // Handles -x (change of sign). BigInt operator-() const { - BigInt ans = *this; - ans.sign = -sign; - return ans; + BigInt res = *this; + res.sign = -sign; + return res; } - // Returs absolute value. BigInt abs() const { - BigInt ans = *this; - ans.sign *= ans.sign; - return ans; + BigInt res = *this; + res.sign *= res.sign; + return res; + } + + ll to_long() const { + ll res = 0; + for (int i = size() - 1; i >= 0; i--) + res = res * base + num[i]; + return res * sign; + } + + friend BigInt gcd(const BigInt &a, const BigInt &b) { + return b.is_zero() ? a : gcd(b, a % b); + } + friend BigInt lcm(const BigInt &a, const BigInt &b) { + return a / gcd(a, b) * b; } // Transforms string into BigInt. @@ -103,9 +234,8 @@ struct BigInt { num.clear(); int pos = 0; - while (pos < (int) s.size() && - (s[pos] == '-' || s[pos] == '+')) - { + while (pos < s.size() && + (s[pos] == '-' || s[pos] == '+')) { if (s[pos] == '-') sign = -sign; ++pos; @@ -127,8 +257,7 @@ struct BigInt { return stream; } - friend ostream& operator<<(ostream &stream, - const BigInt &x) { + friend ostream& operator<<(ostream &stream, const BigInt &x) { if (x.sign == -1) stream << '-'; @@ -139,10 +268,109 @@ struct BigInt { return stream; } + static vector<int> convert_base(const vector<int> &a, + int oldd, int newd) + { + vector<ll> p(max(oldd, newd) + 1); + p[0] = 1; + for (int i = 1; i < p.size(); i++) + p[i] = p[i - 1] * 10; + + ll cur = 0; + int curd = 0; + vector<int> res; + + for (int i = 0; i < a.size(); i++) { + cur += a[i] * p[curd]; + curd += oldd; + + while (curd >= newd) { + res.pb(int(cur % p[newd])); + cur /= p[newd]; + curd -= newd; + } + } + + res.pb((int) cur); + while (!res.empty() && !res.back()) + res.pop_back(); + return res; + } + + static vector<ll> karatsuba(const vector<ll> &a, + const vector<ll> &b) + { + int n = a.size(); + vector<ll> res(n + n); + + if (n <= 32) { + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + res[i + j] += a[i] * b[j]; + return res; + } + + int k = n >> 1; + vector<ll> a1(a.begin(), a.begin() + k); + vector<ll> a2(a.begin() + k, a.end()); + vector<ll> b1(b.begin(), b.begin() + k); + vector<ll> b2(b.begin() + k, b.end()); + + vector<ll> a1b1 = karatsuba(a1, b1); + vector<ll> a2b2 = karatsuba(a2, b2); + + for (int i = 0; i < k; i++) + a2[i] += a1[i]; + for (int i = 0; i < k; i++) + b2[i] += b1[i]; + + vector<ll> r = karatsuba(a2, b2); + for (int i = 0; i < a1b1.size(); i++) r[i] -= a1b1[i]; + for (int i = 0; i < a2b2.size(); i++) r[i] -= a2b2[i]; + + for (int i = 0; i < r.size(); i++) res[i + k] += r[i]; + for (int i = 0; i < a1b1.size(); i++) res[i] += a1b1[i]; + for (int i = 0; i < a2b2.size(); i++) res[i + n] += a2b2[i]; + + return res; + } + + BigInt operator*(const BigInt &x) const { + vector<int> a6 = convert_base(this->num, base_d, 6); + vector<int> b6 = convert_base(x.num, base_d, 6); + + vector<ll> a(all(a6)); + vector<ll> b(all(b6)); + + while (a.size() < b.size()) a.pb(0); + while (b.size() < a.size()) b.pb(0); + while (a.size() & (a.size() - 1)) + a.pb(0), b.pb(0); + + vector<ll> c = karatsuba(a, b); + + BigInt res; + int carry = 0; + res.sign = sign * x.sign; + + for (int i = 0; i < c.size(); i++) { + ll cur = c[i] + carry; + res.pb((int) (cur % 1000000)); + carry = (int) (cur / 1000000); + } + + res.num = convert_base(res.num, 6, base_d); + res.trim(); + return res; + } + // Handles vector operations. int back() const { return num.back(); } bool empty() const { return num.empty(); } size_t size() const { return num.size(); } + + void pop_back() { num.pop_back(); } + void resize(int x) { num.resize(x); } void push_back(int x) { num.push_back(x); } int &operator[](int i) { return num[i]; } diff --git a/algorithms/math/binary_exponentiation.cpp b/algorithms/math/binary_exponentiation.cpp index bda0665f2416948c48bf68ff8ea62450ba02ad7b..e20f965ab12606745050948856cfb9d82c697a75 100644 --- a/algorithms/math/binary_exponentiation.cpp +++ b/algorithms/math/binary_exponentiation.cpp @@ -3,18 +3,15 @@ /// Time: O(log n) /// Space: O(1) -struct BinaryExponentiation { +struct BinExp { ll run(ll x, ll n) { ll ans = 1; - while (n) { if (n & 1) ans = ans * x; - n >>= 1; x = x * x; } - return ans; } }; diff --git a/contests/Cadernaveis/KOCH.cpp b/contests/Cadernaveis/KOCH.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e5cf2391d2465eab4ddf78133824cacfe3abc380 --- /dev/null +++ b/contests/Cadernaveis/KOCH.cpp @@ -0,0 +1,412 @@ +#include <bits/stdc++.h> + +#define EPS 1e-6 +#define MOD 1000000007 +#define inf 0x3f3f3f3f +#define llinf 0x3f3f3f3f3f3f3f3f + +#define fi first +#define se second +#define pb push_back +#define ende '\n' + +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +#define mset(x, y) memset(&x, (y), sizeof(x)) + +using namespace std; + +using ll = long long; +using ii = pair<int,int>; + +const int base = 1000000000; +const int base_d = 9; + +struct BigInt { + int sign; + vector<int> num; + + BigInt() : sign(1) {} + BigInt(ll x) { *this = x; } + BigInt(const string &s) { read(s); } + + void operator=(const BigInt &x) { + sign = x.sign; + num = x.num; + } + + void operator=(ll x) { + sign = 1; + if (x < 0) sign = -1, x = -x; + for (; x > 0; x /= base) + pb(x % base); + } + + BigInt operator+(const BigInt &x) const { + if (sign != x.sign) return *this - (-x); + + + int carry = 0; + BigInt res = x; + + for (int i = 0; i < max(size(), x.size()) || carry; ++i) { + if (i == (int) res.size()) + res.push_back(0); + + res[i] += carry + (i < size() ? num[i] : 0); + carry = res[i] >= base; + if (carry) res[i] -= base; + } + + return res; + } + + BigInt operator-(const BigInt &x) const { + if (sign != x.sign) return *this + (-x); + if (abs() < x.abs()) return -(x - *this); + + int carry = 0; + BigInt res = *this; + + for (int i = 0; i < x.size() || carry; ++i) { + res[i] -= carry + (i < x.size() ? x[i] : 0); + carry = res[i] < 0; + if (carry) res[i] += base; + } + + res.trim(); + return res; + } + + void operator*=(int x) { + if (x < 0) sign = -sign, x = -x; + + int carry = 0; + for (int i = 0; i < size() || carry; ++i) { + if (i == size()) pb(0); + ll cur = num[i] * (ll) x + carry; + + carry = (int) (cur / base); + num[i] = (int) (cur % base); + } + + trim(); + } + + BigInt operator*(int x) const { + BigInt res = *this; + res *= x; + return res; + } + + friend pair<BigInt, BigInt> divmod(const BigInt &a1, + const BigInt &b1) + { + int norm = base / (b1.back() + 1); + BigInt a = a1.abs() * norm; + BigInt b = b1.abs() * norm; + BigInt q, r; + q.resize(a.size()); + + for (int i = a.size() - 1; i >= 0; i--) { + r *= base; + r += a[i]; + + int s1 = r.size() <= b.size() ? 0 : r[b.size()]; + int s2 = r.size() <= b.size() - 1 ? 0 : r[b.size() - 1]; + int d = ((ll) base * s1 + s2) / b.back(); + + r -= b * d; + while (r < 0) r += b, --d; + q[i] = d; + } + + q.sign = a1.sign * b1.sign; + r.sign = a1.sign; + q.trim(); r.trim(); + + return make_pair(q, r / norm); + } + + BigInt operator/(const BigInt &x) const { + return divmod(*this, x).fi; + } + + BigInt operator%(const BigInt &x) const { + return divmod(*this, x).se; + } + + void operator/=(int x) { + if (x < 0) sign = -sign, x = -x; + + for (int i = size() - 1, rem = 0; i >= 0; --i) { + ll cur = num[i] + rem * (ll) base; + num[i] = (int) (cur / x); + rem = (int) (cur % x); + } + + trim(); + } + + BigInt operator/(int x) const { + BigInt res = *this; + res /= x; + return res; + } + + int operator%(int x) const { + if (x < 0) x = -x; + + int m = 0; + for (int i = size() - 1; i >= 0; --i) + m = (num[i] + m * (ll) base) % x; + + return m * sign; + } + + void operator+=(const BigInt &x) { + *this = *this + x; + } + void operator-=(const BigInt &x) { + *this = *this - x; + } + void operator*=(const BigInt &x) { + *this = *this * x; + } + void operator/=(const BigInt &x) { + *this = *this / x; + } + + bool operator<(const BigInt &x) const { + if (sign != x.sign) + return sign < x.sign; + + if (size() != x.size()) + return size() * sign < x.size() * x.sign; + + for (int i = size() - 1; i >= 0; i--) + if (num[i] != x[i]) + return num[i] * sign < x[i] * sign; + + return false; + } + + bool operator>(const BigInt &x) const { + return x < *this; + } + bool operator<=(const BigInt &x) const { + return !(x < *this); + } + bool operator>=(const BigInt &x) const { + return !(*this < x); + } + bool operator==(const BigInt &x) const { + return !(*this < x) && !(x < *this); + } + bool operator!=(const BigInt &x) const { + return *this < x || x < *this; + } + + void trim() { + while (!empty() && !back()) pop_back(); + if (empty()) sign = 1; + } + + bool is_zero() const { + return empty() || (size() == 1 && !num[0]); + } + + BigInt operator-() const { + BigInt res = *this; + res.sign = -sign; + return res; + } + + BigInt abs() const { + BigInt res = *this; + res.sign *= res.sign; + return res; + } + + ll to_long() const { + ll res = 0; + for (int i = size() - 1; i >= 0; i--) + res = res * base + num[i]; + return res * sign; + } + + friend BigInt gcd(const BigInt &a, const BigInt &b) { + return b.is_zero() ? a : gcd(b, a % b); + } + + friend BigInt lcm(const BigInt &a, const BigInt &b) { + return a / gcd(a, b) * b; + } + + void read(const string &s) { + sign = 1; + num.clear(); + + int pos = 0; + while (pos < s.size() && + (s[pos] == '-' || s[pos] == '+')) { + if (s[pos] == '-') + sign = -sign; + ++pos; + } + + for (int i = s.size() - 1; i >= pos; i -= base_d) { + int x = 0; + for (int j = max(pos, i - base_d + 1); j <= i; j++) + x = x * 10 + s[j] - '0'; + num.push_back(x); + } + + trim(); + } + + friend istream& operator>>(istream &stream, BigInt &v) { + string s; stream >> s; + v.read(s); + return stream; + } + + friend ostream& operator<<(ostream &stream, const BigInt &x) { + if (x.sign == -1) + stream << '-'; + + stream << (x.empty() ? 0 : x.back()); + for (int i = x.size() - 2; i >= 0; --i) + stream << setw(base_d) << setfill('0') << x.num[i]; + + return stream; + } + + static vector<int> convert_base(const vector<int> &a, + int oldd, int newd) + { + vector<ll> p(max(oldd, newd) + 1); + p[0] = 1; + for (int i = 1; i < p.size(); i++) + p[i] = p[i - 1] * 10; + + ll cur = 0; + int curd = 0; + vector<int> res; + + for (int i = 0; i < a.size(); i++) { + cur += a[i] * p[curd]; + curd += oldd; + + while (curd >= newd) { + res.pb(int(cur % p[newd])); + cur /= p[newd]; + curd -= newd; + } + } + + res.pb((int) cur); + while (!res.empty() && !res.back()) + res.pop_back(); + return res; + } + + static vector<ll> karatsuba(const vector<ll> &a, + const vector<ll> &b) + { + int n = a.size(); + vector<ll> res(n + n); + + if (n <= 32) { + for (int i = 0; i < n; i++) + for (int j = 0; j < n; j++) + res[i + j] += a[i] * b[j]; + return res; + } + + int k = n >> 1; + vector<ll> a1(a.begin(), a.begin() + k); + vector<ll> a2(a.begin() + k, a.end()); + vector<ll> b1(b.begin(), b.begin() + k); + vector<ll> b2(b.begin() + k, b.end()); + + vector<ll> a1b1 = karatsuba(a1, b1); + vector<ll> a2b2 = karatsuba(a2, b2); + + for (int i = 0; i < k; i++) + a2[i] += a1[i]; + for (int i = 0; i < k; i++) + b2[i] += b1[i]; + + vector<ll> r = karatsuba(a2, b2); + for (int i = 0; i < a1b1.size(); i++) r[i] -= a1b1[i]; + for (int i = 0; i < a2b2.size(); i++) r[i] -= a2b2[i]; + + for (int i = 0; i < r.size(); i++) res[i + k] += r[i]; + for (int i = 0; i < a1b1.size(); i++) res[i] += a1b1[i]; + for (int i = 0; i < a2b2.size(); i++) res[i + n] += a2b2[i]; + + return res; + } + + BigInt operator*(const BigInt &x) const { + vector<int> a6 = convert_base(this->num, base_d, 6); + vector<int> b6 = convert_base(x.num, base_d, 6); + + vector<ll> a(all(a6)); + vector<ll> b(all(b6)); + + while (a.size() < b.size()) a.pb(0); + while (b.size() < a.size()) b.pb(0); + while (a.size() & (a.size() - 1)) + a.pb(0), b.pb(0); + + vector<ll> c = karatsuba(a, b); + + BigInt res; + int carry = 0; + res.sign = sign * x.sign; + + for (int i = 0; i < c.size(); i++) { + ll cur = c[i] + carry; + res.pb((int) (cur % 1000000)); + carry = (int) (cur / 1000000); + } + + res.num = convert_base(res.num, 6, base_d); + res.trim(); + return res; + } + + // Handles vector operations. + int back() const { return num.back(); } + bool empty() const { return num.empty(); } + size_t size() const { return num.size(); } + + void pop_back() { num.pop_back(); } + void resize(int x) { num.resize(x); } + void push_back(int x) { num.push_back(x); } + + int &operator[](int i) { return num[i]; } + int operator[](int i) const { return num[i]; } +}; + +int main() { + ios::sync_with_stdio(0); + cin.tie(0); + + vector<int> fib(1501); + fib[0] = 0; + fib[1] = 1; + for (int i = 2; i <= 1500; ++i) + fib[i] = (fib[i-1] + fib[i-2]) % 1000; + + int t; cin >> t; + for (int cas = 1; cas <= t; ++cas) { + BigInt x; cin >> x; + x = x % BigInt(1500); + cout << setw(3) << setfill('0') << fib[x.to_long()]<< ende; + } + + return 0; +} diff --git a/contests/Cadernaveis/KRAKOVIA.cpp b/contests/Cadernaveis/KRAKOVIA.cpp new file mode 100644 index 0000000000000000000000000000000000000000..847f1c22a349c1af77536609565db2172bc89aeb --- /dev/null +++ b/contests/Cadernaveis/KRAKOVIA.cpp @@ -0,0 +1,267 @@ +#include <bits/stdc++.h> + +#define EPS 1e-6 +#define MOD 1000000007 +#define inf 0x3f3f3f3f +#define llinf 0x3f3f3f3f3f3f3f3f + +#define fi first +#define se second +#define pb push_back +#define ende '\n' + +#define all(x) (x).begin(), (x).end() +#define rall(x) (x).rbegin(), (x).rend() +#define mset(x, y) memset(&x, (y), sizeof(x)) + +using namespace std; + +using ll = long long; +using ii = pair<int,int>; + +const int base = 1000000000; +const int base_d = 9; + +struct BigInt { + int sign = 1; + vector<int> num; + + BigInt() {} + BigInt(ll x) { *this = x; } + BigInt(const string &x) { read(x); } + + void operator=(ll x) { + sign = 1; + if (x < 0) sign = -1, x = -x; + for (; x > 0; x /= base) + num.pb(x % base); + } + + BigInt operator+(const BigInt &x) const { + if (sign != x.sign) return *this - (-x); + + BigInt ans = x; + int carry = 0; + for (int i = 0; i < max(size(), x.size()) || carry; ++i) { + if (i == ans.size()) ans.push_back(0); + + if (i < size()) ans[i] += carry + num[i]; + else ans[i] += carry; + + carry = ans[i] >= base; + if (carry) ans[i] -= base; + } + + return ans; + } + + BigInt operator-(const BigInt& x) const { + if (sign != x.sign) + return *this + (-x); + if (abs() < x.abs()) + return -(x - *this); + + BigInt ans = *this; + int carry = 0; + for (int i = 0; i < x.size() || carry; ++i) { + if (i < x.size()) ans[i] -= carry + x[i]; + else ans[i] -= carry; + + carry = ans[i] < 0; + if (carry) ans[i] += base; + } + + ans.trim(); + return ans; + } + + void operator+=(const BigInt &v) { + *this = *this + v; + } + void operator-=(const BigInt &v) { + *this = *this - v; + } + + void operator*=(int v) { + if (v < 0) sign = -sign, v = -v; + for (int i = 0, carry = 0; i < (int) size() || carry; ++i) { + if (i == (int) size()) + num.push_back(0); + + ll cur = num[i] * (ll) v + carry; + carry = (int) (cur / base); + num[i] = (int) (cur % base); + } + + trim(); + } + + BigInt operator*(int v) const { + BigInt res = *this; + res *= v; + return res; + } + + // Returns pair = (x / y, x % y). + friend pair<BigInt,BigInt> divmod(const BigInt &x, + const BigInt &y) { + int norm = base / (y.back() + 1); + + BigInt a = x.abs() * norm; + BigInt b = y.abs() * norm; + BigInt q, r; + q.num.resize(a.size()); + + for (int i = a.size() - 1; i >= 0; i--) { + r *= base; + r += a[i]; + int s1 = r.size() <= b.size() ? 0 : r.num[b.size()]; + int s2 = r.size() <= b.size() - 1 ? 0 : r.num[b.size() - 1]; + + int d = ((ll) base * s1 + s2) / b.back(); + r -= b * d; + while (r < 0) r += b, --d; + q.num[i] = d; + } + + q.sign = x.sign * y.sign; + r.sign = x.sign; + q.trim(); r.trim(); + return make_pair(q, r / norm); + } + + BigInt operator/(const BigInt &x) const { + return divmod(*this, x).fi; + } + + void operator/=(int v) { + if (v < 0) sign = -sign, v = -v; + + for (int i = (int) size() - 1, rem = 0; i >= 0; --i) { + ll cur = num[i] + rem * (ll) base; + num[i] = (int) (cur / v); + rem = (int) (cur % v); + } + + trim(); + } + + BigInt operator/(int x) const { + BigInt res = *this; + res /= x; + return res; + } + + // Removes leading zeros. + void trim() { + while (!num.empty() && num.back() == 0) + num.pop_back(); + + if (num.empty()) + sign = 1; + } + + bool operator<(const BigInt &x) const { + if (sign != x.sign) + return sign < x.sign; + + if (size() != x.size()) + return (size() * sign) < (x.size() * x.sign); + + for (int i = size() - 1; i >= 0; i--) + if (num[i] != x[i]) + return (num[i] * sign) < (x[i] * x.sign); + + return false; + } + + bool operator==(const BigInt &x) const { return !(*this < x) && !(x < *this); } + bool operator>(const BigInt &x) const { return (x < *this); } + bool operator<=(const BigInt &x) const { return !(x < *this); } + bool operator>=(const BigInt &x) const { return !(*this < x); } + bool operator!=(const BigInt &x) const { return !(*this == x); } + + // Handles -x (change of sign). + BigInt operator-() const { + BigInt ans = *this; + ans.sign = -sign; + return ans; + } + + // Returs absolute value. + BigInt abs() const { + BigInt ans = *this; + ans.sign *= ans.sign; + return ans; + } + + // Transforms string into BigInt. + void read(const string &s) { + sign = 1; + num.clear(); + + int pos = 0; + while (pos < (int) s.size() && + (s[pos] == '-' || s[pos] == '+')) + { + if (s[pos] == '-') + sign = -sign; + ++pos; + } + + for (int i = s.size() - 1; i >= pos; i -= base_d) { + int x = 0; + for (int j = max(pos, i - base_d + 1); j <= i; j++) + x = x * 10 + s[j] - '0'; + num.push_back(x); + } + + trim(); + } + + friend istream& operator>>(istream &stream, BigInt &v) { + string s; stream >> s; + v.read(s); + return stream; + } + + friend ostream& operator<<(ostream &stream, + const BigInt &x) { + if (x.sign == -1) + stream << '-'; + + stream << (x.empty() ? 0 : x.back()); + for (int i = x.size() - 2; i >= 0; --i) + stream << setw(base_d) << setfill('0') << x.num[i]; + + return stream; + } + + // Handles vector operations. + int back() const { return num.back(); } + bool empty() const { return num.empty(); } + size_t size() const { return num.size(); } + void push_back(int x) { num.push_back(x); } + + int &operator[](int i) { return num[i]; } + int operator[](int i) const { return num[i]; } +}; + +int main() { + ios::sync_with_stdio(0); + cin.tie(0); + + int n, f, cas = 1; + while (cin >> n >> f && (n || f)) { + vector<BigInt> v(n); + for (int i = 0; i < n; ++i) + cin >> v[i]; + + BigInt sum = accumulate(all(v), BigInt("0")); + cout << "Bill #" << cas << " costs " << sum << ": each friend should pay " << sum / f << ende; + cout << ende; + cas++; + } + + return 0; +} diff --git a/contests/Cadernaveis/MCAIRO.cpp b/contests/Cadernaveis/MCAIRO.cpp index c65600e4977358bc0108427660ba3051565790b3..5915f7ba0a9fe7a5d88021aa5f3c73bff4cbe076 100644 --- a/contests/Cadernaveis/MCAIRO.cpp +++ b/contests/Cadernaveis/MCAIRO.cpp @@ -60,14 +60,9 @@ int main() { for (int i = 0; i < n; ++i) cin >> x[i] >> y[i]; - int ans = 0; - for (int i = 0; i < n; ++i) { - int val = 1 + bit.query(x[i], y[i]); - bit.update(x[i], y[i], val); - ans = max(ans, val); - } - - cout << ans << ende; + for (int i = 0; i < n; ++i) + bit.update(x[i], y[i], 1 + bit.query(x[i], y[i])); + cout << bit.query(1000, 1000) << ende; } return 0;