扩展欧几里得求逆元
void exgcd ( int a , int b ) { if ( b == 0 ) { x = 1; y = 0; return ; } exgcd ( b , a % b ); int xx , yy; xx = y; yy = x - (a/b) * y; x = xx; y = yy; } int getinv ( int a , int b ) { exgcd ( b , a ); y %= b; if ( y < 0 ) y += b; return y; }
快速幂
ll qpow(ll m, ll k, ll mod) { ll res = 1, t = m; while (k) { if (k & 1) res = res * t % mod; t = t * t % mod; k >>= 1; } return res; }
gcd,lcm
ll gcd(ll m, ll n) { return n == 0 ? m : gcd(n, m % n); } ll lcm(ll m, ll n) { return m * n / gcd(m, n); }
扩展欧几里得求方程
void exgcd(ll A, ll B, ll& x, ll& y) { if (B) exgcd(B, A % B, y, x), y -= A / B * x; else x = 1, y = 0; }
欧拉筛
vector<int> pri;
bool vis[N];
void sieve() { for (int i = 2; i < N; i++) { if (!vis[i]) pri.push_back(i); for (int x : pri) { if ((ll)i * x > N) break; vis[i * x] = 1; if (i % x == 0) break; } } }
判断是否素数
bool isPrime(int num) { if (num == 2 || num == 3) return 1; if (num % 6 != 1 && num % 6 != 5) return 0; int tmp = sqrt(num); for (int i = 5; i <= tmp; i += 6) if (num %i == 0 || num % (i + 2) == 0) return 0; return 1; }
矩阵乘法+快速幂
struct matrix { double mat[2][2]; }; matrix mul(matrix a,matrix b) { matrix res; for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { res.mat[i][j] = 0; for (int k = 0; k < 2; k++) { res.mat[i][j] += a.mat[i][k] * b.mat[k][j]; } } } return res; } matrix powm(matrix a, int n) { matrix res; memset(res.mat,0, sizeof(res.mat)); for (int i = 0; i < 2; i++) { res.mat[i][i] = 1; } matrix tmp = a; while (n) { if (n & 1) res = mul(res, tmp); tmp = mul(tmp, tmp); n >>= 1; } return res; }
map按键值排序 eg. (放弃map排value的想法!)
struct cmp { bool operator() (const pair<string, string> &a , const pair<string, string> &b) { if (a.second != b.second) return a.second < b.second; else return a.first < b.first; } };
Comb
inline int add(int x, int y) { return ((x % mod) + (y % mod)) % mod; } inline int sub(int x, int y) { x -= y; return x < 0 ? x += mod : x; } inline int mul(int x, int y) { return (1ll * (x % mod) * (y % mod)) % mod; } inline int inv(int x) { return qpow(x, mod - 2); } inline int divd(int x, int y) { return (1ll * (x % mod) * inv(y)) % mod; }
namespace Comb { const int maxc = 2000000 + 5; int f[maxc], inv[maxc], finv[maxc]; void init() { inv[1] = 1; for (int i = 2; i < maxc; i++) inv[i] = (mod - mod / i) * 1ll * inv[mod % i] % mod; f[0] = finv[0] = 1; for (int i = 1; i < maxc; i++) { f[i] = f[i - 1] * 1ll * i % mod; finv[i] = finv[i - 1] * 1ll * inv[i] % mod; } } int C(int n, int m) { if (m < 0 || m > n) return 0; return f[n] * 1ll * finv[n - m] % mod * finv[m] % mod; } int S(int n, int m) { // x_1 + x_2 + ... + x_n = m, x_i >= 0 if (n == 0 && m == 0) return 1; return C(m + n - 1, n - 1); } } using Comb::C; int main() { Comb::init(); }
单调队列
class MonotonicQueue { private: deque<int> data; public: void push(int n) { while (!data.empty() && data.back() < n) data.pop_back(); data.push_back(n); } int max() { return data.front(); } void pop(int n) { if (!data.empty() && data.front() == n) data.pop_front(); } };
并查集
int f[200010]; int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); } bool add(int x, int y) { int fx = find(x), fy = find(y); if (fx != fy) { f[fx] = fy; return true; } return false; }