扩展欧几里得求逆元
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;
}