This commit is contained in:
arielherself 2024-05-02 13:31:31 +08:00
parent aaf37a497c
commit 4a333399ab
No known key found for this signature in database
15 changed files with 1243 additions and 261 deletions

View File

@ -1,3 +1,4 @@
vim.cmd("set pumblend=15")
vim.cmd("set expandtab")
vim.cmd("set tabstop=4")
vim.cmd("set softtabstop=4")
@ -88,6 +89,15 @@ local plugins = {
-- Additional lua configuration, makes nvim stuff amazing!
'folke/neodev.nvim',
},
opts = {
-- inlay_hints = { enabled = true, },
-- codelens = { enabled = true, },
},
config = function(_, servers)
for server, opts in pairs(servers) do
require('lspconfig')[server].setup(opts)
end
end,
},
{
"hrsh7th/nvim-cmp",
@ -429,7 +439,7 @@ local plugins = {
},
{ 'Civitasv/cmake-tools.nvim' },
{ 'p00f/cphelper.nvim' },
{ "savq/melange-nvim" },
{ "arielherself/melange-nvim"},
{ 'hrsh7th/vim-vsnip' },
{ 'octarect/telescope-menu.nvim' },
{
@ -444,8 +454,9 @@ local plugins = {
},
config = true
},
{ 'Exafunction/codeium.vim' },
-- { 'Exafunction/codeium.vim' },
{ "mistricky/codesnap.nvim", build = "make" },
{ 'rmagatti/goto-preview' },
}
local opts = {
}
@ -606,6 +617,9 @@ lspconfig.rust_analyzer.setup {
['rust-analyzer'] = {},
},
}
lspconfig.lua_ls.setup {
capabilities = capabilities
}
-- Global mappings.
-- See `:help vim.diagnostic.*` for documentation on any of the below functions
@ -661,7 +675,6 @@ require("lsp_signature").setup({})
vim.keymap.set({'i', 'n', 'v', 'x'}, '<C-z>', '<Nop>', {noremap=true})
vim.keymap.set({'i', 'n', 'v', 'x'}, '<C-c>', '<ESC>', {noremap=true})
vim.keymap.set('i', '<C-v>', '<ESC>PA')
vim.keymap.set('i', '<C-x>', '<ESC>ddi')
vim.keymap.set('i', '<Home>', '<ESC>^i')
vim.keymap.set('i', '<C-a>', '<ESC>ggVG')
@ -873,265 +886,9 @@ require('usage-tracker').setup({
telemetry_endpoint = "" -- you'll need to start the restapi for this feature
})
local function lines(str)
local result = {}
for line in str:gmatch '[^\n]+' do
table.insert(result, line)
end
return result
end
local ls = require('luasnip')
local snip = ls.snippet
local text = ls.text_node
local include_snippet = [[
#pragma GCC optimize("Ofast")
/////////////////////////////////////////////////////////
/**
* Useful Macros
* by subcrip
* (requires C++17)
*/
#include<bits/stdc++.h>
using namespace std;
/* macro helpers */
#define __NARGS(...) std::tuple_size<decltype(std::make_tuple(__VA_ARGS__))>::value
#define __DECOMPOSE_S(a, x) auto x = a;
#define __DECOMPOSE_N(a, ...) auto [__VA_ARGS__] = a;
constexpr void __() {}
#define __AS_PROCEDURE(...) __(); __VA_ARGS__; __()
#define __as_typeof(container) decltype(container)::value_type
/* type aliases */
using ll = int64_t;
using ull = uint64_t;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
/* constants */
constexpr int INF = 0x3f3f3f3f;
constexpr ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
constexpr ll MDL = 1e9 + 7;
constexpr ll PRIME = 998'244'353;
constexpr ll MDL1 = 8784491;
constexpr ll MDL2 = PRIME;
/* random */
mt19937 rd(chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count());
/* bit-wise operations */
#define lowbit(x) ((x) & -(x))
#define popcount(x) (__builtin_popcountll(ll(x)))
#define parity(x) (__builtin_parityll(ll(x)))
#define msp(x) (63LL - __builtin_clzll(ll(x)))
#define lsp(x) (__builtin_ctzll(ll(x)))
/* arithmetic operations */
#define mod(x, y) ((((x) % (y)) + (y)) % (y))
/* fast pairs */
#define upair ull
#define umake(x, y) (ull(x) << 32 | (ull(y) & ((1ULL << 32) - 1)))
#define u1(p) ((p) >> 32)
#define u2(p) ((p) & ((1ULL << 32) - 1))
#define ult std::less<upair>
#define ugt std::greater<upair>
#define ipair ull
#define imake(x, y) (umake(x, y))
#define i1(p) (int(u1(ll(p))))
#define i2(p) (ll(u2(p) << 32) >> 32)
struct ilt {
bool operator()(const ipair& a, const ipair& b) const {
if (i1(a) == i1(b)) return i2(a) < i2(b);
else return i1(a) < i1(b);
}
};
struct igt {
bool operator()(const ipair& a, const ipair& b) const {
if (i1(a) == i1(b)) return i2(a) > i2(b);
else return i1(a) > i1(b);
}
};
/* conditions */
#define loop while (1)
#define if_or(var, val) if (!(var == val)) var = val; else
#define continue_or(var, val) __AS_PROCEDURE(if (var == val) continue; var = val;)
#define break_or(var, val) __AS_PROCEDURE(if (var == val) break; var = val;)
/* hash */
struct safe_hash {
// https://codeforces.com/blog/entry/62393
static uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
struct pair_hash {
template <typename T, typename U>
size_t operator()(const pair<T, U>& a) const {
auto hash1 = safe_hash()(a.first);
auto hash2 = safe_hash()(a.second);
if (hash1 != hash2) {
return hash1 ^ hash2;
}
return hash1;
}
};
/* build data structures */
#define unordered_counter(from, to) __AS_PROCEDURE(unordered_map<__as_typeof(from), size_t, safe_hash> to; for (auto&& x : from) ++to[x];)
#define counter(from, to, cmp) __AS_PROCEDURE(map<__as_typeof(from), size_t, cmp> to; for (auto&& x : from) ++to[x];)
#define pa(a) __AS_PROCEDURE(__typeof(a) pa; pa.push_back({}); for (auto&&x : a) pa.push_back(pa.back() + x);)
#define sa(a) __AS_PROCEDURE(__typeof(a) sa(a.size() + 1); {int n = a.size(); for (int i = n - 1; i >= 0; --i) sa[i] = sa[i + 1] + a[i];};)
#define adj(ch, n) __AS_PROCEDURE(vector<vector<int>> ch((n) + 1);)
#define edge(ch, u, v) __AS_PROCEDURE(ch[u].push_back(v), ch[v].push_back(u);)
#define Edge(ch, u, v) __AS_PROCEDURE(ch[u].push_back(v);)
template <typename T, typename Iterator> pair<size_t, map<T, size_t>> discretize(Iterator __first, Iterator __last) {
set<T> st(__first, __last);
size_t N = 0;
map<T, size_t> mp;
for (auto&& x : st) mp[x] = ++N;
return {N, mp};
}
template <typename T, typename Iterator> pair<size_t, unordered_map<T, size_t, safe_hash>> unordered_discretize(Iterator __first, Iterator __last) {
set<T> st(__first, __last);
size_t N = 0;
unordered_map<T, size_t, safe_hash> mp;
for (auto&& x : st) mp[x] = ++N;
return {N, mp};
}
/* io */
#define untie __AS_PROCEDURE(ios_base::sync_with_stdio(0), cin.tie(NULL))
template<typename T> void __read(T& x) { cin >> x; }
template<typename T, typename... U> void __read(T& x, U&... args) { cin >> x; __read(args...); }
#define read(type, ...) __AS_PROCEDURE(type __VA_ARGS__; __read(__VA_ARGS__);)
#define readvec(type, a, n) __AS_PROCEDURE(vector<type> a(n); for (int i = 0; i < (n); ++i) cin >> a[i];)
#define putvec(a) __AS_PROCEDURE(for (auto&& x : a) cout << x << ' '; cout << endl;)
#define debug(x) __AS_PROCEDURE(cerr << #x" = " << (x) << endl;)
#define debugvec(a) __AS_PROCEDURE(cerr << #a" = "; for (auto&& x : a) cerr << x << ' '; cerr << endl;)
template<typename T, typename U> ostream& operator<<(ostream& out, const pair<T, U>& p) {
out << "{" << p.first << ", " << p.second << "}";
return out;
}
template<typename Char, typename Traits, typename Tuple, std::size_t... Index>
void print_tuple_impl(std::basic_ostream<Char, Traits>& os, const Tuple& t, std::index_sequence<Index...>) {
using swallow = int[]; // guaranties left to right order
(void)swallow { 0, (void(os << (Index == 0 ? "" : ", ") << std::get<Index>(t)), 0)... };
}
template<typename Char, typename Traits, typename... Args>
decltype(auto) operator<<(std::basic_ostream<Char, Traits>& os, const std::tuple<Args...>& t) {
os << "{";
print_tuple_impl(os, t, std::index_sequence_for<Args...>{});
return os << "}";
}
template<typename T> ostream& operator<<(ostream& out, const vector<T>& vec) {
for (auto&& i : vec) out << i << ' ';
return out;
}
/* pops */
#define poptop(q, ...) __AS_PROCEDURE(auto [__VA_ARGS__] = q.top(); q.pop();)
#define popback(q, ...) __AS_PROCEDURE(auto [__VA_ARGS__] = q.back(); q.pop_back();)
#define popfront(q, ...) __AS_PROCEDURE(auto [__VA_ARGS__] = q.front();q.pop_front();)
/* math */
constexpr inline int lg2(ll x) { return x == 0 ? -1 : sizeof(ll) * 8 - 1 - __builtin_clzll(x); }
void __exgcd(ll a, ll b, ll& x, ll& y) {
if (b == 0) {
x = 1, y = 0;
return;
}
__exgcd(b, a % b, y, x);
y -= a / b * x;
}
ll inverse(ll a, ll b) {
ll x, y;
__exgcd(a, b, x, y);
return mod(x, b);
}
/* string algorithms */
vector<int> calc_next(string t) { // pi function of t
int n = (int)t.length();
vector<int> pi(n);
for (int i = 1; i < n; i++) {
int j = pi[i - 1];
while (j > 0 && t[i] != t[j]) j = pi[j - 1];
if (t[i] == t[j]) j++;
pi[i] = j;
}
return pi;
}
vector<int> calc_z(string t) { // z function of t
int m = t.length();
vector<int> z;
z.push_back(m);
pair<int, int> prev = {1, -1};
for (int i = 1; i < m; ++i) {
if (z[i - prev.first] + i <= prev.second) {
z.push_back(z[i - prev.first]);
} else {
int j = max(i, prev.second + 1);
while (j < m && t[j] == t[j - i]) ++j;
z.push_back(j - i);
prev = {i, j - 1};
}
}
return z;
}
vector<int> kmp(string s, string t) { // find all t in s
string cur = t + '#' + s;
int sz1 = s.size(), sz2 = t.size();
vector<int> v;
vector<int> lps = calc_next(cur);
for (int i = sz2 + 1; i <= sz1 + sz2; i++) {
if (lps[i] == sz2) v.push_back(i - 2 * sz2);
}
return v;
}
int period(string s) { // find the length of shortest recurring period
int n = s.length();
auto z = calc_z(s);
for (int i = 1; i <= n / 2; ++i) {
if (n % i == 0 && z[i] == n - i) {
return i;
}
}
return n;
}
/////////////////////////////////////////////////////////
]]
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'include',
namr = 'Useful Macros',
dscr = 'Useful Macros',
},{
text(lines(include_snippet))
})
}
})
-- my snippets
require('snippets')
require('neo-tree').setup {
filesystem = {
@ -1308,3 +1065,8 @@ require('codesnap').setup {
code_font_family = "Fira Code",
has_line_number = true,
}
require('goto-preview').setup {
default_mappings = true;
}

View File

@ -0,0 +1,15 @@
return {
name = "c++ build (cp)",
builder = function()
-- Full path to current file (see :help expand())
local file = vim.fn.expand("%:p")
return {
cmd = { "g++ -std=c++17 " .. file .. " -fsanitize=address -Ofast -Wall && ./a.out < std.in > std.out" },
args = { file },
components = { { "on_output_quickfix", open = true }, "default" },
}
end,
condition = {
filetype = { "cpp" },
},
}

23
lua/snippets/bit.lua Normal file
View File

@ -0,0 +1,23 @@
return [[
template<typename T>
struct BIT {
int n;
vector<T> c;
BIT(size_t n) : n(n), c(n + 1) {}
void add(size_t i, const T& k) {
while (i <= n) {
c[i] += k;
i += lowbit(i);
}
}
T getsum(size_t i) {
T res = {};
while (i) {
res += c[i];
i -= lowbit(i);
}
return res;
}
};
]]

View File

@ -0,0 +1,237 @@
return [[
#pragma GCC optimize("Ofast")
/////////////////////////////////////////////////////////
/**
* Useful Macros
* by subcrip
* (requires C++17)
*/
#include<bits/stdc++.h>
using namespace std;
/* macro helpers */
#define __NARGS(...) std::tuple_size<decltype(std::make_tuple(__VA_ARGS__))>::value
#define __DECOMPOSE_S(a, x) auto x = a;
#define __DECOMPOSE_N(a, ...) auto [__VA_ARGS__] = a;
constexpr void __() {}
#define __AS_PROCEDURE(...) __(); __VA_ARGS__; __()
#define __as_typeof(container) decltype(container)::value_type
/* type aliases */
using ll = int64_t;
using ull = uint64_t;
using pii = pair<int, int>;
using pil = pair<int, ll>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
/* constants */
constexpr int INF = 0x3f3f3f3f;
constexpr ll INFLL = 0x3f3f3f3f3f3f3f3fLL;
constexpr ll MDL = 1e9 + 7;
constexpr ll PRIME = 998'244'353;
constexpr ll MDL1 = 8784491;
constexpr ll MDL2 = PRIME;
/* random */
mt19937 rd(chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now().time_since_epoch()).count());
/* bit-wise operations */
#define lowbit(x) ((x) & -(x))
#define popcount(x) (__builtin_popcountll(ll(x)))
#define parity(x) (__builtin_parityll(ll(x)))
#define msp(x) (63LL - __builtin_clzll(ll(x)))
#define lsp(x) (__builtin_ctzll(ll(x)))
/* arithmetic operations */
#define mod(x, y) ((((x) % (y)) + (y)) % (y))
/* fast pairs */
#define upair ull
#define umake(x, y) (ull(x) << 32 | (ull(y) & ((1ULL << 32) - 1)))
#define u1(p) ((p) >> 32)
#define u2(p) ((p) & ((1ULL << 32) - 1))
#define ult std::less<upair>
#define ugt std::greater<upair>
#define ipair ull
#define imake(x, y) (umake(x, y))
#define i1(p) (int(u1(ll(p))))
#define i2(p) (ll(u2(p) << 32) >> 32)
struct ilt {
bool operator()(const ipair& a, const ipair& b) const {
if (i1(a) == i1(b)) return i2(a) < i2(b);
else return i1(a) < i1(b);
}
};
struct igt {
bool operator()(const ipair& a, const ipair& b) const {
if (i1(a) == i1(b)) return i2(a) > i2(b);
else return i1(a) > i1(b);
}
};
/* conditions */
#define loop while (1)
#define if_or(var, val) if (!(var == val)) var = val; else
#define continue_or(var, val) __AS_PROCEDURE(if (var == val) continue; var = val;)
#define break_or(var, val) __AS_PROCEDURE(if (var == val) break; var = val;)
/* hash */
struct safe_hash {
// https://codeforces.com/blog/entry/62393
static uint64_t splitmix64(uint64_t x) {
// http://xorshift.di.unimi.it/splitmix64.c
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}
};
struct pair_hash {
template <typename T, typename U>
size_t operator()(const pair<T, U>& a) const {
auto hash1 = safe_hash()(a.first);
auto hash2 = safe_hash()(a.second);
if (hash1 != hash2) {
return hash1 ^ hash2;
}
return hash1;
}
};
/* build data structures */
#define unordered_counter(from, to) __AS_PROCEDURE(unordered_map<__as_typeof(from), size_t, safe_hash> to; for (auto&& x : from) ++to[x];)
#define counter(from, to, cmp) __AS_PROCEDURE(map<__as_typeof(from), size_t, cmp> to; for (auto&& x : from) ++to[x];)
#define pa(a) __AS_PROCEDURE(__typeof(a) pa; pa.push_back({}); for (auto&&x : a) pa.push_back(pa.back() + x);)
#define sa(a) __AS_PROCEDURE(__typeof(a) sa(a.size() + 1); {int n = a.size(); for (int i = n - 1; i >= 0; --i) sa[i] = sa[i + 1] + a[i];};)
#define adj(ch, n) __AS_PROCEDURE(vector<vector<int>> ch((n) + 1);)
#define edge(ch, u, v) __AS_PROCEDURE(ch[u].push_back(v), ch[v].push_back(u);)
#define Edge(ch, u, v) __AS_PROCEDURE(ch[u].push_back(v);)
template <typename T, typename Iterator> pair<size_t, map<T, size_t>> discretize(Iterator __first, Iterator __last) {
set<T> st(__first, __last);
size_t N = 0;
map<T, size_t> mp;
for (auto&& x : st) mp[x] = ++N;
return {N, mp};
}
template <typename T, typename Iterator> pair<size_t, unordered_map<T, size_t, safe_hash>> unordered_discretize(Iterator __first, Iterator __last) {
set<T> st(__first, __last);
size_t N = 0;
unordered_map<T, size_t, safe_hash> mp;
for (auto&& x : st) mp[x] = ++N;
return {N, mp};
}
/* io */
#define untie __AS_PROCEDURE(ios_base::sync_with_stdio(0), cin.tie(NULL))
template<typename T> void __read(T& x) { cin >> x; }
template<typename T, typename... U> void __read(T& x, U&... args) { cin >> x; __read(args...); }
#define read(type, ...) __AS_PROCEDURE(type __VA_ARGS__; __read(__VA_ARGS__);)
#define readvec(type, a, n) __AS_PROCEDURE(vector<type> a(n); for (int i = 0; i < (n); ++i) cin >> a[i];)
#define putvec(a) __AS_PROCEDURE(for (auto&& x : a) cout << x << ' '; cout << endl;)
#define debug(x) __AS_PROCEDURE(cerr << #x" = " << (x) << endl;)
#define debugvec(a) __AS_PROCEDURE(cerr << #a" = "; for (auto&& x : a) cerr << x << ' '; cerr << endl;)
template<typename T, typename U> ostream& operator<<(ostream& out, const pair<T, U>& p) {
out << "{" << p.first << ", " << p.second << "}";
return out;
}
template<typename Char, typename Traits, typename Tuple, std::size_t... Index>
void print_tuple_impl(std::basic_ostream<Char, Traits>& os, const Tuple& t, std::index_sequence<Index...>) {
using swallow = int[]; // guaranties left to right order
(void)swallow { 0, (void(os << (Index == 0 ? "" : ", ") << std::get<Index>(t)), 0)... };
}
template<typename Char, typename Traits, typename... Args>
decltype(auto) operator<<(std::basic_ostream<Char, Traits>& os, const std::tuple<Args...>& t) {
os << "{";
print_tuple_impl(os, t, std::index_sequence_for<Args...>{});
return os << "}";
}
template<typename T> ostream& operator<<(ostream& out, const vector<T>& vec) {
for (auto&& i : vec) out << i << ' ';
return out;
}
/* pops */
#define poptop(q, ...) __AS_PROCEDURE(auto [__VA_ARGS__] = q.top(); q.pop();)
#define popback(q, ...) __AS_PROCEDURE(auto [__VA_ARGS__] = q.back(); q.pop_back();)
#define popfront(q, ...) __AS_PROCEDURE(auto [__VA_ARGS__] = q.front();q.pop_front();)
/* math */
constexpr inline int lg2(ll x) { return x == 0 ? -1 : sizeof(ll) * 8 - 1 - __builtin_clzll(x); }
void __exgcd(ll a, ll b, ll& x, ll& y) {
if (b == 0) {
x = 1, y = 0;
return;
}
__exgcd(b, a % b, y, x);
y -= a / b * x;
}
ll inverse(ll a, ll b) {
ll x, y;
__exgcd(a, b, x, y);
return mod(x, b);
}
/* string algorithms */
vector<int> calc_next(string t) { // pi function of t
int n = (int)t.length();
vector<int> pi(n);
for (int i = 1; i < n; i++) {
int j = pi[i - 1];
while (j > 0 && t[i] != t[j]) j = pi[j - 1];
if (t[i] == t[j]) j++;
pi[i] = j;
}
return pi;
}
vector<int> calc_z(string t) { // z function of t
int m = t.length();
vector<int> z;
z.push_back(m);
pair<int, int> prev = {1, -1};
for (int i = 1; i < m; ++i) {
if (z[i - prev.first] + i <= prev.second) {
z.push_back(z[i - prev.first]);
} else {
int j = max(i, prev.second + 1);
while (j < m && t[j] == t[j - i]) ++j;
z.push_back(j - i);
prev = {i, j - 1};
}
}
return z;
}
vector<int> kmp(string s, string t) { // find all t in s
string cur = t + '#' + s;
int sz1 = s.size(), sz2 = t.size();
vector<int> v;
vector<int> lps = calc_next(cur);
for (int i = sz2 + 1; i <= sz1 + sz2; i++) {
if (lps[i] == sz2) v.push_back(i - 2 * sz2);
}
return v;
}
int period(string s) { // find the length of shortest recurring period
int n = s.length();
auto z = calc_z(s);
for (int i = 1; i <= n / 2; ++i) {
if (n % i == 0 && z[i] == n - i) {
return i;
}
}
return n;
}
/////////////////////////////////////////////////////////
]]

93
lua/snippets/exgcd.lua Normal file
View File

@ -0,0 +1,93 @@
return [[
namespace Exgcd {
template <typename T> T abs(T x) { return x < 0 ? -x : x; }
template <typename T>
struct exgcd_solution_t {
T x, y, gcd;
};
template <typename T>
struct diophantine_solution_t {
exgcd_solution_t<T> x_min, y_min;
T range;
};
// solve `ax + by = gcd(a, b)`
template <typename T>
optional<exgcd_solution_t<T>> exgcd(T a, T b) {
if (a < 0 || b < 0 || a == 0 && b == 0) return nullopt;
T x, y, g;
function<void(T, T)> __exgcd = [&__exgcd, &x, &y, &g] (T a, T b) -> void {
if (b == 0) {
g = a, x = 1, y = 0;
} else {
__exgcd(b, a % b);
swap(x, y);
y -= a / b * x;
}
};
__exgcd(a, b);
return {{ x, y, g }};
};
template <typename T>
optional<T> inverse(T a, T b) {
auto raw = exgcd(a, b);
if (raw == nullopt || raw.value().gcd != 1) {
return nullopt;
} else {
return mod(raw.value().x, b);
}
}
// solve { x = a_i (mod n_i) } if n_i's are coprime
template <typename T>
optional<T> crt(const vector<pair<T, T>>& equations) {
T prod = 1;
for (auto&& [a, n] : equations) {
prod *= n;
}
T res = 0;
for (auto&& [a, n] : equations) {
T m = prod / n;
auto m_rev = inverse(m, n);
if (m_rev == nullopt) return nullopt;
res = mod(res + a * mod(m * m_rev.value(), prod), prod);
}
return res;
}
// find minimal non-negative integral solutions of `ax + by = c`. It's not guaranteed that the other variable is non-negative.
template <typename T>
optional<diophantine_solution_t<T>> diophantine(T a, T b, T c, bool force_positive = false) {
if (a < 0 || b < 0 || a == 0 && b == 0) return nullopt;
auto raw = exgcd(a, b).value();
if (c % raw.gcd) {
return nullopt;
} else {
T x = raw.x * c / raw.gcd, y = raw.y * c / raw.gcd;
T kx = force_positive ? (x <= 0 ? (-x) * raw.gcd / b + 1 : 1 - (x + b / raw.gcd - 1) * raw.gcd / b) : (x <= 0 ? ((-x) + b / raw.gcd - 1) * raw.gcd / b : (- x * raw.gcd / b));
T ky = force_positive ? (y <= 0 ? (- 1 - (-y) * raw.gcd / a) : (y + a / raw.gcd - 1) * raw.gcd / a - 1) : (y <= 0 ? (- ((-y) + a / raw.gcd - 1) * raw.gcd / a) : y * raw.gcd / a);
return {{ { x + b * kx / raw.gcd , y - a * kx / raw.gcd , raw.gcd }, { x + b * ky / raw.gcd , y - a * ky / raw.gcd, raw.gcd }, abs(kx - ky) + 1 }};
}
}
// find the minimal non-negative integral solution of `ax = b (mod n)`
template <typename T>
optional<T> congruential(T a, T b, T n) {
if (a == 0) {
if (b != 0) return nullopt;
return 0;
}
if (a < 0 && a != LLONG_MIN && b != LLONG_MIN) a = -a, b = -b;
auto sol = diophantine(a, n, b);
if (sol == nullopt) {
return nullopt;
} else {
return sol.value().x_min.x;
}
}
}
]]

176
lua/snippets/fhq-treap.lua Normal file
View File

@ -0,0 +1,176 @@
return [[
// @link https://www.acwing.com/file_system/file/content/whole/index/content/8807719/
// Everything starts from 1
namespace treap_link {
template <typename T> class prev {
public:
T operator()(const T& a) {
return a - 1;
}
};
template <typename T> class next {
public:
T operator()(const T& a) {
return a + 1;
}
};
}
template <typename T, typename Compare = less<T>,
typename Prev = treap_link::prev<T>,
typename Next = treap_link::next<T>>
class treap {
#define lson fhq[u].l
#define rson fhq[u].r
private:
using size_type = size_t;
using value_type = T;
using reference = value_type&;
using const_reference = const reference;
struct Node {
int key;
size_type l, r, size;
value_type val;
};
Compare __compare;
Prev __prev;
Next __next;
vector<Node> fhq;
size_type cnt, root;
size_type x, y, z;
size_type _size;
void pushup(size_type u) {
fhq[u].size = fhq[lson].size + fhq[rson].size + 1;
}
size_type node(value_type val) {
if (cnt + 1 >= fhq.size()) {
fhq.push_back({});
}
fhq[++cnt].val = val;
fhq[cnt].key = rand();
fhq[cnt].size = 1;
return cnt;
}
void split(size_type u, value_type val, size_type &x, size_type &y) {
if (!u) x = y = 0;
else {
if (!__compare(val, fhq[u].val)) x = u, split(rson, val, rson, y);
else y = u, split(lson, val, x, lson);
pushup(u);
}
}
size_type merge(size_type x, size_type y) {
if (!x || !y) return x + y;
if (fhq[x].key <= fhq[y].key) {
fhq[x].r = merge(fhq[x].r, y);
pushup(x);
return x;
} else {
fhq[y].l = merge(x, fhq[y].l);
pushup(y);
return y;
}
}
value_type askNum(size_type u, size_type rank) {
if (fhq[lson].size + 1 == rank) return fhq[u].val;
if (fhq[lson].size >= rank) return askNum(lson, rank);
else return askNum(rson, rank - fhq[lson].size - 1);
}
public:
treap(Compare __compare = std::less<T>(),
Prev __prev = treap_link::prev<T>(),
Next __next = treap_link::next<T>()) :
fhq(1), cnt(0), root(0), _size(0),
__compare(__compare), __prev(__prev), __next(__next) {}
treap(size_type n, Compare __compare = std::less<T>(),
Prev __prev = treap_link::prev<T>(),
Next __next = treap_link::next<T>()) :
fhq(1), cnt(0), root(0), _size(0) {
fhq.reserve(n + 1);
}
template<typename _InputIterator,
typename = std::_RequireInputIter<_InputIterator>>
treap(_InputIterator __first, _InputIterator __last)
: fhq(1), cnt(0), root(0), _size(0) {
__try {
for (; __first != __last; ++__first) {
insert(*__first);
}
} __catch(...) {
clear();
__throw_exception_again;
}
}
void clear() {
_size = root = cnt = 0;
fill(fhq.begin(), fhq.end(), Node());
}
void insert(value_type val) {
++_size;
split(root, val, x, y);
root = merge(merge(x, node(val)), y);
}
void remove(value_type val) {
assert(contains(val));
--_size;
split(root, val, x, z);
split(x, __prev(val), x, y);
y = merge(fhq[y].l, fhq[y].r);
root = merge(merge(x, y), z);
}
size_type index_of(value_type val) {
split(root, __prev(val), x, y);
size_type res = fhq[x].size + 1;
root = merge(x, y);
return res;
}
value_type at(size_type rank) {
assert(rank > 0 && rank <= _size);
return askNum(root, rank);
}
value_type prev_element(value_type val) {
split(root, __prev(val), x, y);
size_type u = x;
while (rson) u = rson;
root = merge(x, y);
return fhq[u].val;
}
value_type next_element(value_type val) {
split(root, val, x, y);
size_type u = y;
while (lson) u = lson;
root = merge(x, y);
return fhq[u].val;
}
bool contains(value_type val) {
size_type idx = index_of(val);
return idx <= _size && at(idx) == val;
}
size_type size() {
return _size;
}
#undef lson
#undef rson
};
]]

View File

@ -0,0 +1,55 @@
return [[
static vector<ll> power1, power2;
static const ll b = rd();
static const ll INV1 = inverse(b, MDL1);
static const ll INV2 = inverse(b, MDL2);
template <typename _Tp, typename _Sequence = deque<_Tp>>
struct hash_deque {
using hash_type = pll;
ll hash1, hash2;
_Sequence seq;
size_t size() {
return seq.size();
}
void push_back(const _Tp& x) {
hash1 = mod(mod(hash1 * b, MDL1) + mod(x, MDL1), MDL1);
hash2 = mod(mod(hash2 * b, MDL2) + mod(x, MDL2), MDL2);
seq.push_back(x);
}
void push_front(const _Tp& x) {
size_t length = size();
hash1 = mod(hash1 + mod(mod(x, MDL1) * power1[length], MDL1), MDL1);
hash2 = mod(hash2 + mod(mod(x, MDL2) * power2[length], MDL2), MDL2);
seq.push_front(x);
}
void pop_back() {
_Tp e = seq.back(); seq.pop_back();
hash1 = mod(mod(hash1 - mod(e, MDL1), MDL1) * INV1, MDL1);
hash2 = mod(mod(hash2 - mod(e, MDL2), MDL2) * INV2, MDL2);
}
void pop_front() {
_Tp e = seq.front(); seq.pop_front();
int length = seq.size();
hash1 = mod(hash1 - mod(e * power1[length], MDL1), MDL1);
hash2 = mod(hash2 - mod(e * power2[length], MDL2), MDL2);
}
hash_type hash() {
return {hash1, hash2};
}
void clear() {
hash1 = hash2 = 0;
seq.clear();
}
hash_deque(size_t maxn) {
clear();
int c1 = 1, c2 = 1;
for (int i = power1.size(); i < maxn; ++i) {
power1.push_back(c1);
power2.push_back(c2);
c1 = mod(c1 * b, MDL1);
c2 = mod(c2 * b, MDL2);
}
}
};
]]

72
lua/snippets/hash-vec.lua Normal file
View File

@ -0,0 +1,72 @@
return [[
static vector<MLL<MDL1>> power1;
static vector<MLL<MDL2>> power2;
static const ll b = rd();
template <typename _Tp>
struct hash_vec {
using hash_type = pll;
MLL<MDL1> hash1;
MLL<MDL2> hash2;
vector<_Tp> seq;
size_t size() {
return seq.size();
}
void push_back(const _Tp& x) {
hash1 = hash1 * b + x;
hash2 = hash2 * b + x;
seq.push_back(x);
}
void push_front(const _Tp& x) {
size_t length = size();
hash1 += x * power1[length];
hash2 += x * power2[length];
seq.push_front(x);
}
void pop_back() {
_Tp e = seq.back(); seq.pop_back();
hash1 = (hash1 - e) / b;
hash2 = (hash2 - e) / b;
}
void pop_front() {
_Tp e = seq.front(); seq.pop_front();
int length = seq.size();
hash1 -= e * power1[length];
hash2 -= e * power2[length];
}
void set(size_t pos, const _Tp& value) {
int length = seq.size();
int old_value = seq[pos];
hash1 += (value - old_value) * power1[length - 1 - pos];
hash2 += (value - old_value) * power2[length - 1 - pos];
seq[pos] = value;
}
const _Tp& operator[](size_t pos) {
return seq[pos];
}
hash_type hash() {
return {hash1.val, hash2.val};
}
void clear() {
hash1 = 0;
hash2 = 0;
seq.clear();
}
hash_vec(size_t maxn) {
clear();
MLL<MDL1> c1 = 1;
MLL<MDL2> c2 = 1;
for (int i = power1.size(); i < maxn; ++i) {
power1.push_back(c1);
power2.push_back(c2);
c1 *= b;
c2 *= b;
}
}
hash_vec(size_t maxn, const _Tp& init_value) : hash_vec(maxn) {
for (size_t i = 0; i != maxn; ++i) {
push_back(init_value);
}
}
};
]]

181
lua/snippets/init.lua Normal file
View File

@ -0,0 +1,181 @@
local ls = require('luasnip')
local snip = ls.snippet
local text = ls.text_node
local function lines(str)
local result = {}
for line in str:gmatch '[^\n]+' do
table.insert(result, line)
end
return result
end
local cpp_include = require('snippets.cpp-include')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'include',
namr = 'cpp-include',
dscr = 'Useful Macros',
},{
text(lines(cpp_include))
})
}
})
local segtree_generic = require('snippets.segtree-generic')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'segtree',
namr = 'segtree_generic',
dscr = 'Segment Tree with Lazy Propagation',
},{
text(lines(segtree_generic))
})
}
})
local fhq_treap = require('snippets.fhq-treap')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'treap',
namr = 'fhq_treap',
dscr = 'FHQ Treap',
},{
text(lines(fhq_treap))
})
}
})
local fhq_treap = require('snippets.fhq-treap')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'treap',
namr = 'fhq_treap',
dscr = 'FHQ Treap',
},{
text(lines(fhq_treap))
})
}
})
local bit = require('snippets.bit')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'bit',
namr = 'bit',
dscr = 'Bit-Indexed Tree',
},{
text(lines(bit))
})
}
})
local quick_union = require('snippets.quick-union')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'quick_union',
namr = 'quick_union',
dscr = 'Union Find',
},{
text(lines(quick_union))
})
}
})
local sparse_table = require('snippets.sparse-table')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'sparse_table',
namr = 'sparse_table',
dscr = 'Sparse Table',
},{
text(lines(sparse_table))
})
}
})
local hash_deque = require('snippets.hash-deque')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'hash_deque',
namr = 'hash_deque',
dscr = 'Hashable Deque',
},{
text(lines(hash_deque))
})
}
})
local hash_vec = require('snippets.hash-vec')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'hash_vec',
namr = 'hash_vec',
dscr = 'Hashable Vector',
},{
text(lines(hash_vec))
})
}
})
local exgcd = require('snippets.exgcd')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'exgcd',
namr = 'exgcd',
dscr = 'Extended GCD and Related',
},{
text(lines(exgcd))
})
}
})
local lpf = require('snippets.lpf')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'lpf',
namr = 'lpf',
dscr = 'Least Prime Factor',
},{
text(lines(lpf))
})
}
})
local pollard_rho = require('snippets.pollard-rho')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'pollard_rho',
namr = 'pollard_rho',
dscr = 'Pollard-Rho',
},{
text(lines(pollard_rho))
})
}
})
local tarjan = require('snippets.tarjan')
ls.add_snippets(nil, {
cpp = {
snip({
trig = 'tarjan',
namr = 'tarjan',
dscr = 'Tarjan and Related',
},{
text(lines(tarjan))
})
}
})

22
lua/snippets/lpf.lua Normal file
View File

@ -0,0 +1,22 @@
return [[
constexpr int N = 1e7 + 10;
int lpf[N];
void era(int n) {
lpf[0] = lpf[1] = -1;
for (int i = 2; i <= n; ++i) lpf[i] = i;
for (int i = 2; i <= n; ++i) {
if (lpf[i] == i) {
if ((ll)i * i > n) continue;
for (int j = i * i; j <= n; j += i) {
if (lpf[j] == j) {
lpf[j] = i;
}
}
}
}
}
]]

View File

@ -0,0 +1,91 @@
return [[
vector<tuple<int, int, ll>> decompose(ll x) {
vector<tuple<int, int, ll>> res;
for (int i = 2; i * i <= x; i++) {
if (x % i == 0) {
int cnt = 0;
ll pw = 1;
while (x % i == 0) ++cnt, x /= i, pw *= i;
res.emplace_back(i, cnt, pw);
}
}
if (x != 1) {
res.emplace_back(x, 1, x);
}
return res;
}
struct pollard_rho {
ll max_factor;
pollard_rho() : max_factor(0) { srand(time(NULL)); }
ll quick_pow(ll x, ll p, ll mod) {
ll ans = 1;
while (p) {
if (p & 1) ans = (__int128)ans * x % mod;
x = (__int128)x * x % mod;
p >>= 1;
}
return ans;
}
bool Miller_Rabin(ll p) {
if (p < 2) return 0;
if (p == 2) return 1;
if (p == 3) return 1;
ll d = p - 1, r = 0;
while (!(d & 1)) ++r, d >>= 1;
for (ll k = 0; k < 10; ++k) {
ll a = rand() % (p - 2) + 2;
ll x = quick_pow(a, d, p);
if (x == 1 || x == p - 1) continue;
for (int i = 0; i < r - 1; ++i) {
x = (__int128)x * x % p;
if (x == p - 1) break;
}
if (x != p - 1) return 0;
}
return 1;
}
ll Pollard_Rho(ll x) {
ll s = 0, t = 0;
ll c = (ll)rand() % (x - 1) + 1;
int step = 0, goal = 1;
ll val = 1;
for (goal = 1;; goal *= 2, s = t, val = 1) {
for (step = 1; step <= goal; ++step) {
t = ((__int128)t * t + c) % x;
val = (__int128)val * abs(t - s) % x;
if ((step % 127) == 0) {
ll d = gcd(val, x);
if (d > 1) return d;
}
}
ll d = gcd(val, x);
if (d > 1) return d;
}
}
void fac(ll x) {
if (x <= max_factor || x < 2) return;
if (Miller_Rabin(x)) {
max_factor = max(max_factor, x);
return;
}
ll p = x;
while (p >= x) p = Pollard_Rho(x);
while ((x % p) == 0) x /= p;
fac(x), fac(p);
}
// find greatest prime factor of `x`
ll solve(ll x) {
max_factor = 0;
fac(x);
return max_factor;
}
};
]]

View File

@ -0,0 +1,31 @@
return [[
class quick_union {
private:
vector<size_t> c, sz;
public:
quick_union(size_t n) : c(n), sz(n) {
iota(c.begin(), c.end(), 0);
sz.assign(n, 1);
}
size_t query(size_t i) {
if (c[i] != i) c[i] = query(c[i]);
return c[i];
}
void merge(size_t i, size_t j) {
if (connected(i, j)) return;
sz[query(j)] += sz[query(i)];
c[query(i)] = query(j);
}
bool connected(size_t i, size_t j) {
return query(i) == query(j);
}
size_t query_size(size_t i) {
return sz[query(i)];
}
};
]]

View File

@ -0,0 +1,128 @@
return [[
template<typename Addable_Info_t, typename Tag_t, typename Sequence = std::vector<Addable_Info_t>> class segtree {
private:
using size_type = uint64_t;
using info_type = Addable_Info_t;
using tag_type = Tag_t;
size_type _max;
vector<info_type> d;
vector<tag_type> b;
void pull(size_type p) {
d[p] = d[p * 2] + d[p * 2 + 1];
}
void push(size_type p, size_type left_len, size_type right_len) {
d[p * 2].apply(b[p], left_len), d[p * 2 + 1].apply(b[p], right_len);
b[p * 2].apply(b[p]), b[p * 2 + 1].apply(b[p]);
b[p] = tag_type();
}
void set(size_type s, size_type t, size_type p, size_type x, const info_type& c) {
if (s == t) {
d[p] = c;
return;
}
size_type m = s + (t - s >> 1);
if (s != t) push(p, m - s + 1, t - m);
if (x <= m) set(s, m, p * 2, x, c);
else set(m + 1, t, p * 2 + 1, x, c);
d[p] = d[p * 2] + d[p * 2 + 1];
}
void range_apply(size_type s, size_type t, size_type p, size_type l, size_type r, const tag_type& c) {
if (l <= s && t <= r) {
d[p].apply(c, t - s + 1);
b[p].apply(c);
return;
}
size_type m = s + (t - s >> 1);
push(p, m - s + 1, t - m);
if (l <= m) range_apply(s, m, p * 2, l, r, c);
if (r > m) range_apply(m + 1, t, p * 2 + 1, l, r, c);
pull(p);
}
info_type range_query(size_type s, size_type t, size_type p, size_type l, size_type r) {
if (l <= s && t <= r) {
return d[p];
}
size_type m = s + (t - s >> 1);
info_type res = {};
push(p, m - s + 1, t - m);
if (l <= m) res = res + range_query(s, m, p * 2, l, r);
if (r > m) res = res + range_query(m + 1, t, p * 2 + 1, l, r);
return res;
}
void build(const Sequence& a, size_type s, size_type t, size_type p) {
if (s == t) {
d[p] = a[s];
return;
}
int m = s + (t - s >> 1);
build(a, s, m, p * 2);
build(a, m + 1, t, p * 2 + 1);
pull(p);
}
public:
segtree(size_type __max) : d(4 * __max), b(4 * __max), _max(__max - 1) {}
segtree(const Sequence& a) : segtree(a.size()) {
build(a, {}, _max, 1);
}
void set(size_type i, const info_type& c) {
set({}, _max, 1, i, c);
}
void range_apply(size_type l, size_type r, const tag_type& c) {
range_apply({}, _max, 1, l, r, c);
}
void apply(size_type i, const tag_type& c) {
range_apply(i, i, c);
}
info_type range_query(size_type l, size_type r) {
return range_query({}, _max, 1, l, r);
}
info_type query(size_type i) {
return range_query(i, i);
}
Sequence serialize() {
Sequence res = {};
for (size_type i = 0; i <= _max; ++i) {
res.push_back(query(i));
}
return res;
}
const vector<info_type>& get_d() {
return d;
}
};
struct Tag {
ll val = -1;
void apply(const Tag& rhs) {
if (rhs.val != -1)
val = rhs.val;
}
};
struct Info {
ll val = 0;
void apply(const Tag& rhs, size_t len) {
if (rhs.val != -1)
val = rhs.val * len;
}
};
Info operator+(const Info &a, const Info &b) {
return {a.val + b.val};
}
]]

View File

@ -0,0 +1,25 @@
return [[
template<typename _Tp, typename _Op = function<_Tp(const _Tp&, const _Tp&)>> struct sparse_table {
_Op op;
vector<vector<_Tp>> st;
template <typename ReverseIterator>
sparse_table(ReverseIterator __first, ReverseIterator __last, _Op&& __operation) {
op = __operation;
int n = distance(__first, __last);
st = vector<vector<_Tp>>(n, vector<_Tp>(int(log2(n) + 1)));
int i = n - 1;
for (auto it = __first; it != __last; ++it) {
st[i][0] = *it;
for (int j = 1; i + (1 << j) <= n; ++j) {
st[i][j] = op(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
}
i -= 1;
}
}
_Tp query(size_t __start, size_t __end) {
int s = lg2(__end - __start + 1);
return op(st[__start][s], st[__end - (1 << s) + 1][s]);
}
};
]]

71
lua/snippets/tarjan.lua Normal file
View File

@ -0,0 +1,71 @@
return [=[
namespace tarjan {
// Returns the mapping between vertices and their affiliated sccs.
vector<int> scc(const vector<vector<int>>& ch) {
int n = ch.size();
int cnt = 0, scn = 0;
vector<int> dfn(n), low(n), vis(n), st;
vector<int> br(n);
auto tarjan = [&] (auto tarjan, int v) -> void {
dfn[v]=low[v]=++cnt;
st.push_back(v);
vis[v]=1;
for(const auto&u:ch[v])
if(!dfn[u]) tarjan(tarjan, u),low[v]=min(low[v],low[u]);
else if(vis[u])low[v]=min(low[v],dfn[u]);
if(dfn[v]==low[v]){
++scn;
int u;
do u=st.back(), st.pop_back(),vis[u]=0,br[u]=scn; while(u!=v);
}
};
for (int i = 0; i < n; ++i) {
if (!dfn[i]) {
tarjan(tarjan, i);
}
}
return br;
}
// This method can eliminate redundant edges or self-loops
vector<vector<int>> build_scc(const vector<vector<int>>& ch) {
int n = ch.size();
auto br = scc(ch);
int cnt = *max_element(br.begin(), br.end());
vector<unordered_set<int, safe_hash>> rb(cnt + 1);
for (int i = 0; i < n; ++i) {
for (auto&& u : ch[i]) {
if (br[i] != br[u]) rb[br[i]].emplace(br[u]);
}
}
vector<vector<int>> res(cnt + 1);
for (int i = 1; i <= cnt; ++i) {
res[i] = vector<int>(rb[i].begin(), rb[i].end());
}
return res;
}
// This method can eliminate redundant edges or self-loops
// return form: (scc size, children of scc)
vector<pair<size_t, vector<int>>> build_scc_with_size(const vector<vector<int>>& ch) {
int n = ch.size();
auto br = scc(ch);
int cnt = *max_element(br.begin(), br.end());
vector<unordered_set<int, safe_hash>> rb(cnt + 1);
for (int i = 0; i < n; ++i) {
for (auto&& u : ch[i]) {
if (br[i] != br[u]) rb[br[i]].emplace(br[u]);
}
}
vector<pair<size_t, vector<int>>> res(cnt + 1);
for (int i = 1; i <= cnt; ++i) {
res[i].second = vector<int>(rb[i].begin(), rb[i].end());
}
for (int i = 1; i <= n; ++i) {
res[br[i]].first += 1;
}
return res;
}
}
]=]