Fast exp
cpp
int64_t ppow(int64_t n, int64_t p) {
int64_t res = 1;
while (p > 0) {
if (p & 1) {
res = (res * n) % mod;
}
n = (n * n) % mod;
p >>= 1;
}
return res;
}Combinatorics
cpp
void precalc() {
fact[0] = fact[1] = 1;
for (int i = 2; i <= nmax; i++) {
fact[i] = fact[i - 1] * i % mod;
}
invf[nmax] = ppow(fact[nmax], mod - 2);
for (int i = nmax - 1; i >= 0; i--) {
invf[i] = (invf[i + 1] * (i + 1)) % mod;
}
}
int64_t C(int n, int k) {
int64_t val = (fact[n] * invf[k] % mod) * invf[n - k] % mod;
return val;
}Eratosthenes
cpp
// true -> nu e prim
ciur[0] = true;
ciur[1] = true;
for(int i=2; i*i<=1000000; i++) {
if(ciur[i] == false) {
for(int j=2; j*i<=1000000; j++) {
ciur[j*i] = true;
}
}
}Partial sums
cpp
// pe vector:
for(int i = 1 ; i <= n ; i++)
sp[i] = sp[i-1] + v[i];
int sum = sp[dr] - sp[st-1];
// pe matrice
for(int i = 1 ; i <= n ; i ++)
for(int j = 1 ; j <= m ; j ++)
sp[i][j] = sp[i-1][j] + sp[i][j-1] - sp[i-1][j-1] + a[i][j];
int is,js; // coltul stanga sus
int ij,jj; // coltul dreapta jos
int sum = sp[ij][jj] - sp[is-1][jj] - sp[ij][js-1] + sp[is-1][js-1];Lee’s algorithm
cpp
void Lee(int istart ,int jstart) {
queue<pair<int,int>> Q;
Q.push(make_pair(istart , jstart));
//marcare pozitie de start
A[istart][jstart] = 1;
while(! Q.empty()) { // cat timp coada este nevida
int i = Q.front().first, j = Q.front().second;
for(int k = 0 ; k < 4 ; k ++) {
int iv = i + di[k], jv = j + dj[k]; // coordonatele vecinului
if(iv >= 1 && iv <= n && jv >= 1 && jv <= m // element în matrice
&& A[iv][jv] == 0) { // element liber si nemarcat
// marcam elementul vecin cu o valoare mai mare
A[iv][jv] = A[i][j] + 1;
// il adaugam in coada
Q.push(make_pair(iv , jv));
}
}
Q.pop(); // eliminam din coada
}
}Big numbers
cpp
struct big_int {
int length;
int digits[4096];
void read(std::istream &in) {
std::string buffer;
in >> buffer;
for (int i = buffer.size() - 1; i >= 0; i--) {
digits[length++] = static_cast<int>(buffer[i] - '0');
}
}
void read_as_vec(std::istream &in) {
in >> length;
for (int i = length - 1; i >= 0; i--)
in >> digits[i];
}
void read_as_int(std::istream &in) {
int a;
in >> a;
do {
digits[length++] = a % 10;
a /= 10;
} while (a);
}
void output(std::ostream &out) {
for (int i = length - 1; i >= 0; i--)
out << digits[i];
}
big_int operator+(big_int &other) const {
big_int result{};
result.length = std::max(length, other.length);
int t = 0;
for (int i = 0; i < result.length; i++) {
result.digits[i] = digits[i] + other.digits[i] + t;
t = result.digits[i] / 10;
result.digits[i] %= 10;
}
if (t == 1)
result.digits[result.length++] = 1;
return result;
}
big_int operator-(big_int &other) const {
big_int result{};
result.length = length;
int t = 0;
for (int i = other.length + 1; i <= length;)
other.digits[i++] = 0;
for (int i = 0; i < result.length; i++) {
result.digits[i] = digits[i] - (other.digits[i] + t);
if (result.digits[i] < 0)
t = 1;
else
t = 0;
if (t == 1)
result.digits[i] += 10;
}
while (result.digits[result.length - 1] == 0 && result.length > 1)
result.length--;
return result;
}
big_int operator*(big_int &other) const {
big_int result{};
result.length = length + other.length - 1;
int t = 0;
for (int i = 0; i < length; i++) {
for (int j = 0; j < other.length; j++) {
result.digits[i + j] += digits[i] * other.digits[j];
}
}
for (int i = 0; i < result.length; i++) {
t += result.digits[i];
result.digits[i] = t % 10;
t /= 10;
}
if (t) {
result.digits[result.length++] = t;
}
while (result.digits[result.length - 1] == 0 && result.length > 1)
result.length--;
return result;
}
big_int &operator+=(big_int &other) {
*this = *this + other;
return *this;
}
big_int &operator-=(big_int &other) {
*this = *this - other;
return *this;
}
big_int &operator*=(big_int &other) {
*this = *this * other;
return *this;
}
};
Geometry
https://drive.google.com/file/d/105SxWBXSiUTFBtsoE_hl0cxUZLJAzmBU/view
-
distanta dintre doua puncte
-
distanta dintre un punct si o dreapta
-
panta unei drepte
-
arii
-
baleiere
- infasuratoare convexa
Segment tree
cpp
template <typename T>
class segment_tree {
public:
segment_tree(int n) { sg = vector<T>(4 * n + 1); }
void build(T *v, int curr, int tl, int tr) {
if (tl == tr) {
sg[curr] = v[tl];
} else {
int tm = (tl + tr) / 2;
build(v, curr * 2, tl, tm);
build(v, curr * 2 + 1, tm + 1, tr);
sg[curr] = sg[curr * 2] + sg[curr * 2 + 1];
}
}
void update(int curr, int tl, int tr, int new_pos, int new_val) {
if (tl == tr) {
sg[curr] = new_val;
} else {
int tm = (tl + tr) / 2;
if (new_pos <= tm)
update(curr * 2, tl, tm, new_pos, new_val);
else
update(curr * 2 + 1, tm + 1, tr, new_pos, new_val);
sg[curr] = sg[curr * 2] ^ sg[curr * 2 + 1];
}
}
T query(int curr, int tl, int tr, int l, int r) {
if (l > r)
return 0;
if (l == tl && r == tr)
return sg[curr];
int tm = (tl + tr) / 2;
return query(curr * 2, tl, tm, l, min(r, tm)) ^
query(curr * 2 + 1, tm + 1, tr, max(l, tm + 1), r);
}
private:
vector<T> sg;
};Trie
cpp
#include <iostream>
#include <string>
using namespace std;
const int nmax = 5000;
const int kmax = 1e6;
const int mod = 1e9 + 7;
template <size_t Size>
class trie {
public:
trie() {}
void insert(const string &s) {
int node = 0;
for (size_t i = 0; i < s.size(); i++) {
if (!tree[node][s[i] - 'a'])
tree[node][s[i] - 'a'] = ++ct;
node = tree[node][s[i] - 'a'];
}
stop[node] = true;
}
int search(int x, const string &s, int dp[]) {
int node = 0, ans = 0;
for (size_t i = x; i < s.size(); i++) {
if (!tree[node][s[i] - 'a'])
return ans;
node = tree[node][s[i] - 'a'];
if (stop[node]) {
ans = (ans + dp[i + 1]) % mod;
}
}
return ans;
}
private:
int tree[Size + 1][26];
bool stop[Size + 1];
int ct = 0;
};
int k, dp[nmax + 1];
string n, s;
trie<kmax + 1> t;
int main() {
cin >> n >> k;
while (k--) {
cin >> s;
t.insert(s);
}
dp[n.size()] = 1;
for (int i = n.size() - 1; i >= 0; i--) {
dp[i] = t.search(i, n, dp);
}
cout << dp[0] << '\n';
return 0;
}