From 1970f40ba0371a40b051b5d3679ade35b3bdd14f Mon Sep 17 00:00:00 2001 From: Code Lich Date: Fri, 25 Apr 2025 11:36:28 +0700 Subject: [PATCH] modify bigint snippet --- lua/custom/snippets/edhliicpp.lua | 253 ++++++++++++++++-------------- 1 file changed, 134 insertions(+), 119 deletions(-) diff --git a/lua/custom/snippets/edhliicpp.lua b/lua/custom/snippets/edhliicpp.lua index f6e5b007..804e7a55 100644 --- a/lua/custom/snippets/edhliicpp.lua +++ b/lua/custom/snippets/edhliicpp.lua @@ -84,138 +84,153 @@ ls.add_snippets('cpp', { '}', }, }), - s( - 'bigint', + s('bigint', { t { - 'const ll BASE = 1000000000;', - 'const int BASE_DIGITS = 9;', - '', - '// By edhlii and GPT :>', 'struct BigInt {', - ' vector digits;', - ' BigInt() {}', - ' BigInt(long long v) {', - ' while (v) {', - ' digits.push_back(v % BASE);', - ' v /= BASE;', - ' }', + ' string value;', + ' bool negative;', + ' BigInt() : value("0"), negative(false) {}', + ' BigInt(const string &s) { fromString(s); }', + ' void fromString(const string &s) {', + ' int i = 0;', + ' negative = false;', + ' value.clear();', + " if (s[i] == '-') {", + ' negative = true;', + ' i++;', + " } else if (s[i] == '+')", + ' i++;', + " while (i < (int)s.size() && s[i] == '0')", + ' i++;', + ' value = s.substr(i);', + ' if (value.empty())', + ' value = "0", negative = false;', ' }', - ' BigInt(const string &s) { read(s); }', - ' void read(const string &s) {', - ' digits.clear();', - ' int len = s.size();', - ' for (int i = len; i > 0; i -= BASE_DIGITS) {', - ' int start = max(0, i - BASE_DIGITS);', - ' int length = i - start;', - ' digits.push_back(stoll(s.substr(start, length)));', - ' }', - ' trim();', + ' string toString() const {', + ' return (negative && value != "0" ? "-" : "") + value;', ' }', - ' void trim() {', - ' while (!digits.empty() && digits.back() == 0)', - ' digits.pop_back();', + ' friend ostream &operator<<(ostream &os, const BigInt &b) {', + ' return os << b.toString();', ' }', - ' friend ostream &operator<<(ostream &out, const BigInt &a) {', - ' if (a.digits.empty()) {', - ' out << 0;', - ' return out;', - ' }', - ' out << a.digits.back();', - ' for (int i = a.digits.size() - 2; i >= 0; --i)', - " out << setw(BASE_DIGITS) << setfill('0') << a.digits[i];", - ' return out;', + ' int absCompare(const BigInt &other) const {', + ' if (value.size() != other.value.size())', + ' return value.size() < other.value.size() ? -1 : 1;', + ' return value.compare(other.value);', ' }', - ' BigInt operator+(const BigInt &other) const {', - ' BigInt res;', - ' long long carry = 0;', - ' size_t n = max(digits.size(), other.digits.size());', - ' for (size_t i = 0; i < n || carry; ++i) {', - ' long long sum = carry;', - ' if (i < digits.size())', - ' sum += digits[i];', - ' if (i < other.digits.size())', - ' sum += other.digits[i];', - ' res.digits.push_back(sum % BASE);', - ' carry = sum / BASE;', - ' }', - ' return res;', - ' }', - ' BigInt operator-(const BigInt &other) const {', - ' BigInt res = *this;', - ' long long carry = 0;', - ' for (size_t i = 0; i < other.digits.size() || carry; ++i) {', - ' res.digits[i] -= carry + (i < other.digits.size() ? other.digits[i] : 0);', - ' carry = res.digits[i] < 0;', - ' if (carry)', - ' res.digits[i] += BASE;', - ' }', - ' res.trim();', - ' return res;', - ' }', - ' BigInt operator*(const BigInt &other) const {', - ' BigInt res;', - ' res.digits.resize(digits.size() + other.digits.size());', - ' for (size_t i = 0; i < digits.size(); i++) {', - ' long long carry = 0;', - ' for (size_t j = 0; j < other.digits.size() || carry; j++) {', - ' long long cur =', - ' res.digits[i + j] +', - ' digits[i] * (j < other.digits.size() ? other.digits[j] : 0) + carry;', - ' res.digits[i + j] = cur % BASE;', - ' carry = cur / BASE;', - ' }', - ' }', - ' res.trim();', - ' return res;', + ' bool operator==(const BigInt &other) const {', + ' return negative == other.negative && value == other.value;', ' }', ' bool operator<(const BigInt &other) const {', - ' if (digits.size() != other.digits.size())', - ' return digits.size() < other.digits.size();', - ' for (int i = digits.size() - 1; i >= 0; i--) {', - ' if (digits[i] != other.digits[i])', - ' return digits[i] < other.digits[i];', - ' }', - ' return false;', + ' if (negative != other.negative)', + ' return negative;', + ' int cmp = absCompare(other);', + ' return negative ? cmp > 0 : cmp < 0;', ' }', - ' bool operator<=(const BigInt &other) const { return !(other < *this); }', - ' pair divmod(const BigInt &other) const {', - ' BigInt quotient, remainder;', - ' quotient.digits.resize(digits.size());', - ' for (int i = digits.size() - 1; i >= 0; i--) {', - ' remainder.digits.insert(remainder.digits.begin(), digits[i]);', - ' remainder.trim();', - ' int low = 0, high = BASE - 1, mid, curDigit = 0;', - ' while (low <= high) {', - ' mid = (low + high) / 2;', - ' BigInt t = other * BigInt(mid);', - ' if (t <= remainder) {', - ' curDigit = mid;', - ' low = mid + 1;', - ' } else {', - ' high = mid - 1;', - ' }', - ' }', - ' quotient.digits[i] = curDigit;', - ' remainder = remainder - other * BigInt(curDigit);', + ' bool operator>(const BigInt &other) const { return other < *this; }', + ' BigInt operator+(const BigInt &other) const {', + ' if (negative == other.negative) {', + ' return BigInt(add(value, other.value), negative);', + ' } else {', + ' int cmp = absCompare(other);', + ' if (cmp == 0)', + ' return BigInt("0");', + ' if (cmp > 0)', + ' return BigInt(sub(value, other.value), negative);', + ' else', + ' return BigInt(sub(other.value, value), other.negative);', ' }', - ' quotient.trim();', - ' remainder.trim();', + ' }', + ' BigInt operator-(const BigInt &other) const {', + ' BigInt negOther = other;', + ' negOther.negative = !other.negative;', + ' return *this + negOther;', + ' }', + ' BigInt operator*(const BigInt &other) const {', + " string result(value.size() + other.value.size(), '0');", + ' for (int i = value.size() - 1; i >= 0; --i) {', + ' int carry = 0;', + ' for (int j = other.value.size() - 1; j >= 0; --j) {', + " int tmp = (value[i] - '0') * (other.value[j] - '0') +", + " (result[i + j + 1] - '0') + carry;", + " result[i + j + 1] = tmp % 10 + '0';", + ' carry = tmp / 10;', + ' }', + ' result[i] += carry;', + ' }', + ' int i = 0;', + " while (i < (int)result.size() - 1 && result[i] == '0')", + ' i++;', + ' return BigInt(result.substr(i), negative != other.negative);', + ' }', + ' BigInt operator/(const BigInt &other) const {', + ' return divmod(*this, other).first;', + ' }', + ' BigInt operator%(const BigInt &other) const {', + ' return divmod(*this, other).second;', + ' }', + 'private:', + ' BigInt(const string &s, bool neg) : value(s), negative(neg) {', + ' if (value == "0")', + ' negative = false;', + ' }', + ' static string add(const string &a, const string &b) {', + ' string res;', + ' int carry = 0, i = a.size() - 1, j = b.size() - 1;', + ' while (i >= 0 || j >= 0 || carry) {', + ' int sum = carry;', + " if (i >= 0) sum += a[i--] - '0';", + " if (j >= 0) sum += b[j--] - '0';", + " res += sum % 10 + '0';", + ' carry = sum / 10;', + ' }', + ' reverse(res.begin(), res.end());', + ' return res;', + ' }', + ' static string sub(const string &a, const string &b) {', + ' string res;', + ' int borrow = 0, i = a.size() - 1, j = b.size() - 1;', + ' while (i >= 0) {', + " int diff = a[i] - '0' - (j >= 0 ? b[j--] - '0' : 0) - borrow;", + ' if (diff < 0) diff += 10, borrow = 1;', + ' else borrow = 0;', + " res += diff + '0';", + ' i--;', + ' }', + " while (res.size() > 1 && res.back() == '0')", + ' res.pop_back();', + ' reverse(res.begin(), res.end());', + ' return res;', + ' }', + ' static pair divmod(BigInt a, BigInt b) {', + ' if (b.value == "0")', + ' throw runtime_error("Division by zero");', + ' BigInt quotient, remainder;', + ' quotient.value.clear();', + ' remainder = BigInt("0");', + ' for (char digit : a.value) {', + ' remainder = remainder * BigInt("10") + BigInt(string(1, digit));', + ' int count = 0;', + ' while (remainder > b || remainder == b) {', + ' remainder = remainder - b;', + ' count++;', + ' }', + " quotient.value += count + '0';", + ' }', + ' int i = 0;', + " while (i < (int)quotient.value.size() - 1 && quotient.value[i] == '0')", + ' i++;', + ' quotient.value = quotient.value.substr(i);', + ' quotient.negative = a.negative != b.negative;', + ' remainder.negative = a.negative;', + ' if (quotient.value == "0")', + ' quotient.negative = false;', + ' if (remainder.value == "0")', + ' remainder.negative = false;', ' return {quotient, remainder};', ' }', - ' BigInt operator/(const BigInt &other) const { return divmod(other).first; }', - ' BigInt operator%(const BigInt &other) const { return divmod(other).second; }', - ' BigInt &operator+=(const BigInt &other) { return *this = *this + other; }', - ' BigInt &operator-=(const BigInt &other) { return *this = *this - other; }', - ' BigInt &operator*=(const BigInt &other) { return *this = *this * other; }', - ' BigInt &operator/=(const BigInt &other) {', - ' return *this = divmod(other).first;', - ' }', - ' BigInt &operator%=(const BigInt &other) {', - ' return *this = divmod(other).second;', - ' }', '};', - } - ), + }, + }), s('rollinghash', { t { 'struct RollingHash {',