Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const int Dig = 10;
- struct BigNum {
- deque<int> num;
- int sign = 1;
- //constructor
- BigNum() {
- }
- BigNum(long long x) {
- num.clear();
- if (x < 0)
- sign = -1, x = -x;
- if (x == 0)
- num.push_back(x);
- while (x > 0) {
- num.push_back(x % Dig);
- x /= Dig;
- }
- }
- BigNum(int x) {
- num.clear();
- if (x < 0)
- sign = -1, x = -x;
- if (x == 0)
- num.push_back(x);
- while (x > 0) {
- num.push_back(x % Dig);
- x /= Dig;
- }
- }
- BigNum(const BigNum &x) {
- sign = x.sign;
- num = x.num;
- }
- // change to int
- friend int BtoI(const BigNum &x) {
- int res = 0, t = 1;
- for (int i = 0; i < x.num.size(); i++)
- res += t * x.num[i];
- return res;
- }
- //absolut
- friend BigNum abs(const BigNum &x) {
- BigNum res = x;
- res.sign = 1;
- return res;
- }
- //clear 0
- void clr() {
- while (!num.empty() and !num.back())
- num.pop_back();
- }
- //normalize
- void normalize() {
- (*this).clr();
- int carry = 0;
- for (int i = 0; i < num.size(); i++) {
- int t = num[i] + carry;
- if (t < 0) {
- t += Dig;
- carry = -1;
- num[i] = t;
- }
- else {
- num[i] = t % Dig;
- carry = t / Dig;
- }
- }
- if (carry > 0)
- num.push_back(carry);
- if (carry < 0) {
- sign *= -1;
- num.push_back(-carry);
- }
- (*this).clr();
- if (num.empty())
- sign = 1;
- }
- //is 0
- bool isZero() {
- (*this).normalize();
- return num.empty();
- }
- //compare operators
- bool operator<(const BigNum &x) const {
- if (sign != x.sign)
- return sign < x.sign;
- bool res = false, flag = false;
- if (num.size() != x.num.size()) {
- res = (num.size() < x.num.size());
- flag = true;
- }
- else {
- for (int i = num.size() - 1; i >= 0; i--)
- if (num[i] != x.num[i]) {
- flag = true;
- res = (num[i] < x.num[i]);
- break;
- }
- }
- if (!flag)
- return false;
- if (sign == -1)
- return !res;
- return res;
- }
- bool operator==(const BigNum &x) const {
- if (sign == x.sign and num.size() == x.num.size()) {
- bool res = true;
- for (int i = 0; i < num.size() and res; i++)
- if (num[i] != x.num[i])
- res = false;
- return res;
- }
- else
- return false;
- }
- bool operator<=(const BigNum &x) const {
- return (((*this) < x) or ((*this) == x));
- }
- bool operator>(const BigNum &x) const {
- return (!((*this) <= x));
- }
- bool operator>=(const BigNum &x) const {
- return (!((*this) < x));
- }
- bool operator!=(const BigNum &x) const {
- return (!((*this) == x));
- }
- friend BigNum max(const BigNum &x, const BigNum &y) {
- return (x > y? x: y);
- }
- friend BigNum min(const BigNum &x, const BigNum &y) {
- return (x < y? x: y);
- }
- //math operators
- BigNum operator+(const BigNum &x) const {
- if (sign == x.sign) {
- BigNum res;
- res.sign = sign;
- for (int i = 0; i < max(x.num.size(), num.size()); i++) {
- int t = (i >= num.size()? 0: num[i]) + (i >= x.num.size()? 0: x.num[i]);
- res.num.push_back(t);
- }
- res.normalize();
- return res;
- }
- if (sign == -1)
- return x - abs(*this);
- else
- return (*this) - abs(x);
- }
- BigNum operator-(const BigNum &x) const {
- if (sign == x.sign) {
- BigNum res, a = abs(*this), b = abs(x);
- a.clr();
- b.clr();
- if (a == b) {
- res = 0;
- return res;
- }
- if (b < a) {
- for (int i = 0; i < a.num.size(); i++) {
- int t = a.num[i] - (i >= b.num.size()? 0: b.num[i]);
- res.num.push_back(t);
- }
- res.normalize();
- }
- else {
- for (int i = 0; i < b.num.size(); i++) {
- int t = b.num[i] - (i >= a.num.size()? 0: a.num[i]);
- res.num.push_back(t);
- }
- res.normalize();
- res.sign *= -1;
- }
- if (sign == -1)
- res.sign *= -1;
- return res;
- }
- if (sign == -1) {
- BigNum res = abs(*this) + x;
- res.sign *= -1;
- return res;
- }
- else
- return (*this) + abs(x);
- }
- void operator+=(const BigNum &x) {
- (*this) = (*this) + x;
- }
- void operator-=(const BigNum &x) {
- (*this) = (*this) - x;
- }
- void operator++() {
- (*this) += 1;
- }
- BigNum operator++(int) {
- BigNum res;
- ++(*this);
- return res;
- }
- void operator--() {
- (*this) -= 1;
- }
- BigNum operator--(int) {
- BigNum res;
- --(*this);
- return res;
- }
- BigNum operator*(const BigNum &x) const {
- BigNum res;
- BigNum a = (*this), b = x;
- if (a.isZero() or b.isZero())
- return 0;
- a.clr();
- b.clr();
- for (int i = 0; i < b.num.size(); i++) {
- BigNum t;
- for (int j = 1; j <= i; j++)
- t.num.push_back(0);
- for (int j = 0; j < a.num.size(); j++)
- t.num.push_back(a.num[j] * b.num[i]);
- t.normalize();
- res += t;
- }
- res.normalize();
- res.sign = a.sign * b.sign;
- return res;
- }
- void operator*=(const BigNum &x) {
- (*this) = (*this) * x;
- }
- friend pair<BigNum, BigNum> dmod(const BigNum &x, const BigNum &y) {
- BigNum res, a = abs(x), b = abs(y), carry;
- res.sign = y.sign * x.sign;
- a.clr();
- b.clr();
- if (b.isZero())
- return {-1, -1};
- if (a < b) {
- return {0, x};
- }
- int cnt = a.num.size() - 1;
- for (int i = a.num.size() - 1; carry < b; i--) {
- carry.num.push_front(a.num[i]);
- cnt = i - 1;
- }
- for (int i = 1; i <= 10; i++) {
- BigNum t = b * i;
- if (t > carry) {
- res.num.push_front(i - 1);
- t -= b;
- carry -= t;
- break;
- }
- }
- for (int i = cnt; i >= 0; i--) {
- carry.num.push_front(a.num[i]);
- carry.normalize();
- if (carry >= b) {
- for (int j = 1; j <= 10; j++) {
- BigNum t = b * j;
- if (t > carry) {
- res.num.push_front(j - 1);
- t -= b;
- carry -= t;
- break;
- }
- }
- }
- else {
- res.num.push_front(0);
- }
- }
- res.normalize();
- if (res.sign == -1)
- carry = y - x;
- return {res, carry};
- }
- BigNum operator/(const BigNum &x) const {
- pair<BigNum, BigNum> res = dmod((*this), x);
- return res.first;
- }
- void operator/=(const BigNum &x) {
- (*this) = (*this) / x;
- }
- BigNum operator%(const BigNum &x) const {
- pair<BigNum, BigNum> res = dmod((*this), x);
- return res.second;
- }
- void operator%=(const BigNum &x) {
- (*this) = (*this) % x;
- }
- friend BigNum pow(const BigNum &x, const BigNum &y) {
- BigNum tmp = y;
- if (tmp.isZero())
- return 1;
- BigNum res = 1, t = y, a = x;
- pair<BigNum, BigNum> dm;
- while (t > 0) {
- if ((t % 2) == 1)
- res = res * a;
- a *= a;
- t /= 2;
- }
- return res;
- }
- friend BigNum gcd(BigNum x, BigNum y) {
- return (y.isZero()? x: gcd(y, x % y));
- }
- friend BigNum lcm(const BigNum &x, const BigNum &y) {
- return (x * y) / gcd(x, y);
- }
- friend BigNum sqrt(const BigNum &x) {
- if (x.sign == -1)
- return -1;
- BigNum carry, res, lef;
- deque<pair<int, int>> t;
- for (int i = 0; i < x.num.size(); i += 2) {
- if (i + 1 == x.num.size())
- t.push_front({x.num[i], 1});
- else
- t.push_front({x.num[i] + x.num[i + 1] * 10, 2});
- }
- for (int i = 0; i < t.size(); i++) {
- if (t[i].second == 1)
- carry.num.push_front(t[i].first);
- else
- carry.num.push_front(t[i].first / 10), carry.num.push_front(t[i].first % 10);
- carry.normalize();
- lef.num.push_front(0);
- for (int i = 1; i <= 10; i++) {
- lef.num[0] = i;
- BigNum tmp = (lef) * i;
- if (tmp > carry) {
- lef.num[0] = i - 1;
- tmp = lef * (i - 1);
- carry -= tmp;
- lef += (i - 1);
- res.num.push_front(i - 1);
- break;
- }
- }
- }
- res.normalize();
- return res;
- }
- //string to BigNum and BigNum to string
- void toBig(string &s) {
- if (s[0] == '-') {
- sign = -1;
- s = s.substr(1);
- }
- else
- sign = 1;
- reverse(s.begin(), s.end());
- num.clear();
- for (int i = (s[0] == '-'); i < s.size(); i += Dig / 10) {
- string sp;
- for (int j = i; j < i + (Dig / 10); j++)
- sp += s[j];
- long long t = stol(sp);
- num.push_back(t);
- }
- }
- friend string to_string(const BigNum &x) {
- string res;
- if (x.num.empty()) {
- res += '0';
- return res;
- }
- if (x.sign == -1)
- res += '-';
- for (int i = x.num.size() - 1; i >= 0; i--) {
- string t = to_string(x.num[i]);
- reverse(t.begin(), t.end());
- res += t;
- }
- return res;
- }
- //change base
- friend BigNum change_base(const BigNum &a, const int y, const int x) {
- if (y == x)
- return a;
- BigNum res, t = change_base_rev(a, y, 10);
- t.normalize();
- while (t > 0) {
- res.num.push_back(BtoI(t % x));
- t /= x;
- }
- return res;
- }
- friend BigNum change_base_rev(const BigNum &a, const int y, const int x) {
- if (y == x)
- return a;
- if (x == 10) {
- BigNum res, t = 1, b = a;
- b.clr();
- for (int i = 0; i < b.num.size(); i++)
- res += t * b.num[i], t *= y;
- return res;
- }
- BigNum t = change_base_rev(a, y, 10);
- return change_base(t, 10, x);
- }
- friend BigNum CB(const BigNum &a, int y, int x) {
- if (x > y)
- return change_base_rev(a, y, x);
- return change_base(a, y, x);
- }
- //bitwisse operator
- BigNum operator^(const BigNum &x) const {
- BigNum res, a = change_base(*this, 10, 2), b = change_base(x, 10, 2);
- for (int i = 0; i < max(a.num.size(), b.num.size()); i++) {
- int d1 = 0, d2 = 0;
- if (i < a.num.size())
- d1 = a.num[i];
- if (i < b.num.size())
- d2 = b.num[i];
- res.num.push_back(d1 ^ d2);
- }
- res.clr();
- res = change_base_rev(res, 2, 10);
- res.normalize();
- return res;
- }
- BigNum operator&(const BigNum &x) const {
- BigNum res, a = change_base(*this, 10, 2), b = change_base(x, 10, 2);
- for (int i = 0; i < max(a.num.size(), b.num.size()); i++) {
- int d1 = 0, d2 = 0;
- if (i < a.num.size())
- d1 = a.num[i];
- if (i < b.num.size())
- d2 = b.num[i];
- res.num.push_back(d1 & d2);
- }
- res.clr();
- res = change_base_rev(res, 2, 10);
- res.normalize();
- return res;
- }
- BigNum operator|(const BigNum &x) const {
- BigNum res, a = change_base(*this, 10, 2), b = change_base(x, 10, 2);
- for (int i = 0; i < max(a.num.size(), b.num.size()); i++) {
- int d1 = 0, d2 = 0;
- if (i < a.num.size())
- d1 = a.num[i];
- if (i < b.num.size())
- d2 = b.num[i];
- res.num.push_back(d1 | d2);
- }
- res.clr();
- res = change_base_rev(res, 2, 10);
- res.normalize();
- return res;
- }
- void operator^=(const BigNum &x) {
- (*this) = (*this) ^ x;
- }
- void operator&=(const BigNum &x) {
- (*this) = (*this) & x;
- }
- void operator|=(const BigNum &x) {
- (*this) = (*this) | x;
- }
- BigNum operator<<(const BigNum &x) {
- BigNum res = change_base((*this), 10, 2);
- for (BigNum i = 0; i < x; i++)
- res.num.push_front(0);
- res = change_base_rev(res, 2, 10);
- res.normalize();
- return res;
- }
- BigNum operator>>(const BigNum &x) {
- BigNum res = change_base((*this), 10, 2);
- BigNum t = (int)res.num.size();
- for (BigNum i = 0; i < min(x, t); i++)
- res.num.pop_front();
- res = change_base_rev(res, 2, 10);
- res.normalize();
- return res;
- }
- void operator>>=(const BigNum &x) {
- (*this) = (*this) >> x;
- }
- void operator<<=(const BigNum &x) {
- (*this) = (*this) << x;
- }
- //cin and cout
- friend istream& operator>>(istream &stream, BigNum &x) {
- string s;
- stream >> s;
- x.toBig(s);
- return stream;
- }
- friend ostream& operator<<(ostream &stream, BigNum &x) {
- if (x.num.empty()) {
- stream << 0;
- return stream;
- }
- if (!x.num.empty() and x.sign == -1)
- stream << '-';
- stream << (x.num.empty() ? 0 : x.num.back());
- for (int i = (int) x.num.size() - 2; i >= 0; i--)
- stream << x.num[i];
- return stream;
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement