-- print 'Custom C++ snippets loaded!' local ls = require 'luasnip' local s = ls.snippet local t = ls.text_node local i = ls.insert_node local fmt = require('luasnip.extras.fmt').fmt local rep = require('luasnip.extras').rep ls.add_snippets('cpp', { s('cpptemplate', { t { '#include ', '#define fi first', '#define se second', 'using namespace std;', 'typedef long long ll;', 'typedef unsigned long long ull;', 'const int N = 1000006;', 'const ll MOD = 1000000007;', '', 'int main() {', ' ios_base::sync_with_stdio(false);', ' cin.tie(0);', ' cout.tie(0);', '', ' cout << "edhlii\\n";', '}', }, }), s('segtree', { t { 'struct SegTree {', ' int n;', ' vector tree;', '', ' inline int combine(int a, int b) {', ' // TODO: chỉnh sửa hàm combine cho phù hợp (vd: min(a, b), max(a, b), a + b, ...)', ' return a + b;', ' }', '', ' SegTree(const vector &arr) {', ' n = arr.size();', ' tree.resize(n << 1);', ' for (int i = 0; i < n; ++i)', ' tree[i + n] = arr[i];', ' for (int i = n - 1; i > 0; --i)', ' tree[i] = combine(tree[i << 1], tree[i << 1 | 1]);', ' }', '', ' inline void update(int pos, int val) {', ' pos += n;', ' tree[pos] = val;', ' for (pos >>= 1; pos; pos >>= 1)', ' tree[pos] = combine(tree[pos << 1], tree[pos << 1 | 1]);', ' }', '', ' inline int query(int l, int r) {', ' int resL = 0, resR = 0; // TODO: chỉnh phần tử đơn vị phù hợp', ' l += n;', ' r += n;', ' while (l < r) {', ' if (l & 1)', ' resL = combine(resL, tree[l++]);', ' if (r & 1)', ' resR = combine(tree[--r], resR);', ' l >>= 1;', ' r >>= 1;', ' }', ' return combine(resL, resR);', ' }', '};', }, }), s('binpow', { t { 'll binpow(ll a, ll b, ll c) {', ' ll res = 1;', ' while (b != 0) {', ' if (b & 1) {', ' res = (res * a) % c;', ' }', ' b = b >> 1;', ' a = (a * a) % c;', ' }', ' return res;', '}', }, }), s('bigint', { t { 'struct BigInt {', ' 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;', ' }', ' string toString() const {', ' return (negative && value != "0" ? "-" : "") + value;', ' }', ' friend ostream &operator<<(ostream &os, const BigInt &b) {', ' return os << b.toString();', ' }', ' 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);', ' }', ' bool operator==(const BigInt &other) const {', ' return negative == other.negative && value == other.value;', ' }', ' bool operator<(const BigInt &other) const {', ' 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; }', ' 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);', ' }', ' }', ' 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};', ' }', '};', }, }), s('rollinghash', { t { 'struct RollingHash {', ' using ll = long long;', ' ll base, mod;', ' vector power;', ' vector prefix_hash;', ' RollingHash(const string &s, ll base, ll mod) : base(base), mod(mod) {', ' int n = s.size();', ' power.resize(n + 1, 1);', ' prefix_hash.resize(n + 1, 0);', ' for (int i = 0; i < n; ++i) {', ' power[i + 1] = (__int128)power[i] * base % mod;', ' prefix_hash[i + 1] = ((__int128)prefix_hash[i] * base + s[i]) % mod;', ' }', ' }', ' ll get_hash(int l, int r) {', ' ll hash_r = prefix_hash[r + 1];', ' ll hash_l = (__int128)prefix_hash[l] * power[r - l + 1] % mod;', ' ll res = (hash_r - hash_l + mod) % mod;', ' return res;', ' }', '};', }, }), s( 'fib', fmt( [[ pair {}(ll {}) {{ if ({} == 0) return {{0, 1}}; auto p = {}({} >> 1); ll a = p.first; ll b = p.second; ll c = (a * ((2 * b % MOD - a + MOD) % MOD)) % MOD; ll d = ((a * a) % MOD + (b * b) % MOD) % MOD; if ({} & 1) {{ return {{d, (c + d) % MOD}}; }} else {{ return {{c, d}}; }} }} ]], { i(1, 'fibonacci'), -- function name i(2, 'n'), -- input variable rep(2), -- reuse n rep(1), -- reuse function name rep(2), -- reuse n rep(2), -- reuse n } ) ), })