常用技巧

扩展欧几里得求逆元

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;
}
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;
}

快速幂

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);
}

欧拉筛

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; } } }

矩阵乘法+快速幂

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;
}

Comb

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;
}

ST+dfs序求lca

ll dfn[N][2], id[N << 1], s, n, m, tot;
vector<ll> g[N];
void dfs(ll u, ll fa) {
    dfn[u][0] = dfn[u][1] = ++tot;
    id[tot] = u;
    for (auto to : g[u]) {
        if (to != fa) {
            dfs(to, u);
            dfn[u][1] = ++tot;
            id[tot] = u;
        }
    }
}

class ST {
    static ll lg[N];
    ll n;
    function<ll(ll, ll)> cmp;
    vector<vector<ll>> table;
public:
    ST(ll* arr, ll _n, function<ll(ll, ll)>_cmp = [](ll a, ll b) {return a < b ? a : b; })
        : n(_n), cmp(_cmp)
    {
        if (!lg[0]) {
            lg[0] = -1;
            rep(i, 1, N - 1) {
                lg[i] = lg[i / 2] + 1;
            }
        }
        table = vector<vector<ll>>(lg[n] + 1, vector<ll>(n + 1));
        rep(i, 1, n) {
            table[0][i] = arr[i];
        }
        rep(i, 1, lg[n]) {
            table[0][i] = arr[i];
            for (ll j = 1;j + (1ll << i) - 1 <= n ; j++) {
                table[i][j] = cmp(table[i - 1][j], table[i - 1][j + (1<<(i-1))]);
            }
        }
    }
    ll qry(ll x, ll y) {
        ll t = lg[y - x + 1];
        return cmp(table[t][x], table[t][y - (1ll << t) + 1]);
    }
};
ll ST::lg[N];

二分

//求最小
int getAnswer(int l, int r) {
    int mid;
    while(l < r) {
        mid = (r + l) / 2;
        if(check(mid)) {
            r = mid;
        }
        else {
            l = mid + 1;
        }
    }
}
//求最大
int getAnswer(int l, int r) {
    int mid;
    while (l<r) {
        mid = (r + l + 1) / 2;
        if (check(mid)) {
            l = mid;
        }
        else {
            r = mid - 1;
        }
    }
}

next数组

vector<int> prefix_function(string s) {
  int n = (int)s.length();
  vector<int> pi(n);
  for (int i = 1; i < n; i++) {
    int j = pi[i - 1];
    while (j > 0 && s[i] != s[j]) j = pi[j - 1];
    if (s[i] == s[j]) j++;
    pi[i] = j;
  }
  return pi;
}

posted @ 2020-06-03 00:01  DeaL57  阅读(99)  评论(2编辑  收藏  举报