Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions content/contest/template.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ void solve() {
signed main() {
cin.tie(nullptr)->sync_with_stdio(false);
int t = 1;
cin >> t;
while (t--)
solve();
// cin >> t;
while (t--) solve();
return 0;
}

Expand Down
56 changes: 56 additions & 0 deletions content/data-structures/BinaryTrie.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Author: Ramez
* Description: binary trie that supports update(val, op),
* where op = +1 to insert, op = –1 to erase and query(x) → ans is the maximum XOR you can
* achieve between x and any value currently in the trie.
* Time: $O(1)$ time, $O(N)$ space
*/

struct node {
int ch[2]{}, frq[2]{}, sz{};

int& operator[](int x) {
return ch[x];
}
};

const int M = 60;

struct BinaryTrie {
vector<node> nodes;

int newNode() { return nodes.emplace_back(), nodes.size() - 1; }

void init() { nodes.clear(), newNode(); }

BinaryTrie() { init(); }

void update(int val, int op) { /// 1 -> add , -1 -> delete
int u = 0;
for (int i = M - 1; i >= 0; --i) {
int v = val >> i & 1;
if (!nodes[u][v]) {
nodes[u][v] = newNode();
}
nodes[u].frq[v] += op;
nodes[u].sz += op;
u = nodes[u][v];
}
nodes[u].sz++;
}

int query(int x) {
int ans = 0, u = 0;
for (int i = M - 1; i >= 0 && u >= 0; --i) {
int v = x >> i & 1;
if (nodes[u].frq[v]) {
u = nodes[u][v];
}
else {
u = nodes[u][!v];
ans |= 1LL << i;
}
}
return ans;
}
};
5 changes: 1 addition & 4 deletions content/data-structures/DSU.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
/**
* Author: Lukas Polacek
* Date: 2009-10-26
* License: CC0
* Source: folklore
* Author: Ramez
* Description: Disjoint-set data structure.
* Time: $O(\alpha(N))$
*/
Expand Down
26 changes: 26 additions & 0 deletions content/data-structures/FenwickRUPQ.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/**
* Author: Ramez Medhat
* Description: Range Update, Point Query
* Time: O(logN)
*/
struct FenwickRUPQ {
int n;
vi f;
FenwickRUPQ(int _n) : n(_n), f(n + 1, 0) {}

void update(int idx, int val) {
for (; idx <= n; idx += idx & -idx)
f[idx] += val;
}

void rangeAdd(int l, int r, int val) {
update(l, val);
if (r + 1 <= n) update(r + 1, -val);
}

int pointQuery(int idx) {
int res = 0;
for (; idx > 0; idx -= idx & -idx) res += f[idx];
return res;
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
#pragma once

template<class T>
struct SubMatrix {
struct PrefixSum2D {
vector<vector<T>> p;
SubMatrix(vector<vector<T>>& v) {
int R = sz(v), C = sz(v[0]);
p.assign(R+1, vector<T>(C+1));
rep(r,0,R) rep(c,0,C)
p[r+1][c+1] = v[r][c] + p[r][c+1] + p[r+1][c] - p[r][c];
PrefixSum2D(vector<vector<T>>& v) {
int R = v.size(), C = v[0].size();
p.assign(R + 1, vector<T>(C + 1));
for (int r = 0; r < R; r++) for (int c = 0; c < C; c++)
p[r + 1][c + 1] = v[r][c] + p[r][c + 1] + p[r + 1][c] - p[r][c];
}
T sum(int u, int l, int d, int r) {
return p[d][r] - p[d][l] - p[u][r] + p[u][l];
Expand Down
70 changes: 70 additions & 0 deletions content/data-structures/Trie.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Author: Ramez
* Description: Trie
* Time: $O(1)$ time, $O(N)$ space
*/

struct Trie {
struct Node {
Node* child[26];
int IsEnd, Prefix;
Node() {
memset(child, 0, sizeof child);
IsEnd = Prefix = 0;
}
};

Node* root = new Node();

void insert(string& s)
{
Node* cur = root;
for (auto it : s)
{
int idx = it - 'a';
if (cur->child[idx] == 0)
{
cur->child[idx] = new Node();
}
cur = cur->child[idx];
cur->Prefix++;
}
cur->IsEnd++;
}

bool searchWord(string& s)
{
Node* cur = root;
for (auto it : s)
{
int idx = it - 'a';
if (cur->child[idx] == 0)return 0;
cur = cur->child[idx];
}
return cur->IsEnd;
}

int countWord(string& s)
{
Node* cur = root;
for (auto it : s)
{
int idx = it - 'a';
if (cur->child[idx] == 0)return 0;
cur = cur->child[idx];
}
return cur->IsEnd;
}

int countPrefix(string& s)
{
Node* cur = root;
for (auto it : s)
{
int idx = it - 'a';
if (cur->child[idx] == 0)return 0;
cur = cur->child[idx];
}
return cur->Prefix;
}
};
9 changes: 8 additions & 1 deletion content/data-structures/chapter.tex
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ \chapter{Data structures}
\kactlimport{LazySegmentTree.h}
\kactlimport{MergeSortTree.h}
\kactlimport{FenwickPURQ.cpp}
\kactlimport{FenwickRUPQ.cpp}
\kactlimport{FenwickRURQ.cpp}
\kactlimport{Fenwick2d.h}
\kactlimport{Fenwick2dAdd.h}
\kactlimport{Fenwick2dXor.h}
\kactlimport{OrderStatisticTree.h}
\kactlimport{HashMap.h}
\kactlimport{LazySegmentTree.h}
\kactlimport{DSU.h}
\kactlimport{DSURollback.h}
\kactlimport{SubMatrix.h}
\kactlimport{PrefixSum2D.h}
\kactlimport{Matrix.h}
\kactlimport{LineContainer.h}
\kactlimport{Treap.h}
\kactlimport{RMQ.h}
\kactlimport{MoQueries.h}
\kactlimport{MergeSortTree.h}
\kactlimport{Trie.cpp}
\kactlimport{BinaryTrie.cpp}


62 changes: 62 additions & 0 deletions content/number-theory/Combinatorics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* Author: Ramez
* Description: Function to solve combinatorics problems.
* Time: O(n) for init and O(1) for query
*/

namespace combinatorics {
vector<int> fact, inv, invFact;

int pwmod(int a, int b) {
a %= MOD;
int result = 1;
while (b > 0) {
if (b & 1) result = (result * a) % MOD;
a = (a * a) % MOD;
b /= 2;
}
return result;
}

int inverse(int x) { return pwmod(x, MOD - 2); }
int multiply(int a, int b) { return ((a % MOD) * (b % MOD)) % MOD; }
int divide(int a, int b) { return multiply(a, inverse(b)); }

void init(int n) {
fact.resize(n + 1); inv.resize(n + 1); invFact.resize(n + 1);
fact[0] = fact[1] = inv[0] = inv[1] = invFact[0] = invFact[1] = 1;
for (int i = 2; i <= n; ++i){
fact[i] = fact[i - 1] * i % MOD;
inv[i] = MOD - ((MOD / i) * inv[MOD % i]) % MOD;
invFact[i] = invFact[i - 1] * inv[i] % MOD;
}
}

int nPr(int n, int r) {
if (n < 0 || r < 0 || r > n) return 0;
return fact[n] * invFact[n - r] % MOD;
}

int nCr(int n, int r) {
if (n < 0 || r < 0 || r > n) return 0;
return fact[n] * invFact[r] % MOD * invFact[n - r] % MOD;
}

int nPrLinear(int n, int r){
int answer = 1;
for (int i = n - r + 1; i <= n; i++){
answer = multiply(answer, i);
}
return answer;
}

int nCrLinear(int n, int r){
int answer = 1;
for (int i = r + 1; i <= n; i++){
answer = multiply(answer, i);
answer = divide(answer, i - r);
}
return answer;
}
};
using namespace combinatorics;
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ vi eratosthenes() {
for (int i : pr) isPrime[i] = 1;
return pr;
}

16 changes: 16 additions & 0 deletions content/number-theory/IsPrime.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Author: Ramez Medhat
* Description: Checks if a number is prime or not
* Time: $O(\sqrt{n})$
* Status: Tested
*/


bool isPrime(int n) {
if (n == 2) return true;
if (n == 1 || n % 2 == 0) return false;
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) return false;
}
return true;
}
21 changes: 21 additions & 0 deletions content/number-theory/LinearSieve.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Author: Ramez Medhat
* Description: just like normal sieve but faster
* Time: lim=100'000'000 $\approx$ 0.8 s. Runs 30\% faster if only odd indices are stored.
* Status: Tested
*/

vi linearSieve(int n) {
vector<bool> isPr(n + 1, 1);
vi primes;
isPr[0] = isPr[1] = 0;
for (int i = 2; i <= n; i++) {
if (isPr[i]) primes.push_back(i);
for (int p : primes) {
if (i * p >= n + 1) break;
isPr[i * p] = 0;
if (i % p == 0) break;
}
}
return primes;
}
17 changes: 7 additions & 10 deletions content/number-theory/ModPow.h
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
/**
* Author: Noam527
* Date: 2025-04-24
* Date: 2019-04-24
* License: CC0
* Source: ezz
* Source: folklore
* Description:
* Status: tested
*/
#pragma once

const int mod = 1000000007; // faster if const

int modpow(int a, int b) {
int res = 1;
while (b) {
if (b & 1) res = res * a % mod;
a = a * a % mod;
b >>= 1;
}
return res;
int modpow(int b, int e) {
int ans = 1;
for (; e; b = b * b % mod, e /= 2)
if (e & 1) ans = ans * b % mod;
return ans;
}
12 changes: 5 additions & 7 deletions content/number-theory/Ncr.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/**
* Author: ezz
* Description: Precomputes factorials and inverse factorials modulo mod, call
* build\_fact once before using nCr.
* Description: Precomputes factorials and inverse factorials modulo mod, call build\_fact once before using nCr.
*/

#include "ModPow.h"
Expand All @@ -10,20 +9,19 @@ vector<int> fact = {1}, inv = {1};

void build_fact(int n = 2e6) {

fact.resize(n + 1);
inv.resize(n + 1);

for (int i = 1; i <= n; i++)
fact.push_back(fact.back() * i % mod);
rep(i, 1, n + 1)
fact.push_back(1LL * fact.back() * i % mod);

inv[n] = modpow(fact[n], mod - 2);
for (int i = n - 1; i >= 0; --i)
inv[i] = inv[i + 1] * (i + 1) % mod;
inv[i] = 1LL * inv[i + 1] * (i + 1) % mod;
}
int ncr(int n, int r) {
if (r < 0 || r > n)
return 0;
return fact[n] * inv[r] % mod * inv[n - r] % mod;
// For npr: return fact[n] * inv[n - r] % mod;
// ncr(n + r - 1, n) for stars and bars
}

Loading