Aurora的模板集合

模板题

数学

快速幂

传送门:P1226 【模板】快速幂||取余运算

ll ksm(ll a, ll b, ll mod) {
      ll ans = 1;
      while(b) {
      if(b & 1) ans = ans * a % mod;
      a = a * a % mod; b >>= 1;
      }
      return ans % mod;
}

线性筛

传送门:P3383 【模板】线性筛素数

int pri[maxn];    // 存筛出来的素数 

bool flag[maxn];  // flag[i] = false 表示i是素数,flag[i] = true 表示i不是素数 

void work() {
	flag[1] = true;
	for(int i = 2; i <= n; i++) {
		if(!flag[i]) pri[++cnt] = i;
		for(int j = 1; j <= cnt && i * pri[j] <= n; j++) {
			flag[i * pri[j]] = true;
			if(i % pri[j] == 0) break;   // pri[j + 1] 一定不是 i * pri[j + 1] 最小的因子了,停止继续往下筛 
		}
	}
}

乘法逆元

费马小定理

只有模数(p)为质数的时候能用。

#define ll long long

ll ksm(ll a, ll b, ll mod) {
	ll ans = 1;
	while(b) {
		if(b & 1) ans = ans * a % mod;
		a = a * a % mod; b >>= 1;
	}
	return ans;
}

ll work(ll a, ll p) {return ksm(a, p - 2, p);} // 求a在模p意义下的逆元

拓展欧几里得

void ex_gcd(ll a, ll b, ll &x, ll &y) {
	if(b == 0) {
		x = 1; y = 0;
		return;
	}
	ex_gcd(b, a % b, x, y);
	ll tmp = x; x = y; y = tmp - (a / b) * y;
}

ll work(ll a, ll p) {
	ll x, y;
	ex_gcd(a, p, x, y);
	return (x % p + p) % p;
}

图论

LCA

传送门:P3379 【模板】最近公共祖先(LCA)

code:

void dfs(int u) { // 倍增预处理
	for(int i = 1; i <= 21; i++) f[u][i] = f[f[u][i - 1]][i - 1];
	for(int i = h[u]; i; i = e[i].nex) {
	      if(e[i].to == f[u][0]) continue;
	      f[e[i].to][0] = u; de[e[i].to] = de[u] + 1;
	      dfs(e[i].to);
	}
}

void make_it() { // 另一种倍增预处理
	de[s] = 1; f[s][0] = s;
	dfs(s);
//	for(int j = 1; j <= 21; j++)
//	for(int i = 1; i <= n; i++)
//	f[i][j] = f[f[i][j - 1]][j - 1]; 不在DFS中处理完f数组而是在这里处理也是可以的
}

int query(int x, int y) { // 查询
	if(de[x] < de[y]) swap(x, y);
	for(int i = 21; i >= 0; i--) if(de[x] - (1 << i) >= de[y]) x = f[x][i];
	if(x == y) return x;
	for(int i = 21; i >= 0; i--) if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
	return f[x][0];
}

缩点

Tarjan

传送门:P3387 【模板】缩点

code:

void tarjan(int u) {
	low[u] = dfn[u] = ++dfncnt; sta.push(u);
	for(int i = h[u]; i; i = e[i].nex) {
		int v = e[i].to;
		if(!dfn[v]) {tarjan(v); low[u] = min(low[u], low[v]);}
		else if(!scc[v]) low[u] = min(low[u], dfn[v]);
	}
	if(dfn[u] == low[u]) {
		scccnt++;
		while(sta.top() != u) {p[scccnt] += a[sta.top()]; scc[sta.top()]= scccnt; siz[scccnt]++; sta.pop();}
		p[scccnt] += a[sta.top()]; scc[sta.top()] = scccnt; siz[scccnt]++; sta.pop();
	}
}

void MakeScc() { // 缩点,建立缩点后的图
	for(int i = 1; i <= n; i++) if(!dfn[i]) tarjan(i);
	for(int i = 1; i <= m; i++) {
	      int x = scc[e[i].from], y = scc[e[i].to];
	      if(x != y) addd(x, y);	
	}
}

数据结构

ST表

传送门1:P3865 【模板】ST表

传送门2:ST 表-OI Wiki

操作:查询区间最大值。

code:

void Pre() { // log_2(x) 预处理对数
      logn[1] = 0; logn[2] = 1;
      for(int i = 3; i <= 100005; i++) logn[i] = logn[i >> 1] + 1;
}

void SetUp { // 建表
      pre();
      for(int i = 1; i <= n; i++) f[i][0] = a[i];
      for(int j = 1; j <= 21; j++)
      for(int i = 1; i + (1 << j) - 1 <= n; i++)
      f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}

void query(int x, int y) { // 查询
      int s = logn[y - x + 1];
      printf("%d
", max(f[x][s], f[y - (1 << s) + 1][s]));
}

树状数组

树状数组1

传送门1:P3374 【模板】树状数组 1

传送门2:树状数组-OI Wiki

操作:

  1. 将某一个数加上(x)
  2. 求出某区间每一个数的和

code:

int lowbit(int x) {return x & -x;}

void build() {
      for(int i = 1; i <= n; i++) {
            t[i] = t[i] + c[i];
            int j = i + lowbit(i);
            if(j <= n) t[j] = t[j] + t[i];
      }
}

void update(int x, int k) {
      while(x <= n) {
            t[x] = t[x] + k;
            x = x + lowbit(x);
      }
}

int query(int x) {
      int ans = 0;
      while(x) {
            ans = ans + t[x];
            x = x - lowbit(x);
      }
      return ans;
}

树状数组2

转送门:P3368 【模板】树状数组 2

操作:

  1. 将某区间每一个数数加上(x)
  2. 求出某一个数的值。

code:

ll lowbit(ll x) {return x & -x;}

void build() {
      for(ll i = 1; i <= n; i++) {
            t[i] = 0;
            ll j = i + lowbit(i);
            if(j <= n) t[j] = t[j] + t[i];
      }
}

void update(ll x, ll k) {
      while(x <= n) {
            t[x] = t[x] + k;
            x = x + lowbit(x);
      }
}

ll query(ll x) {
      ll ans = 0;
      while(x) {
            ans = ans + t[x];
            x = x - lowbit(x);
      }
      return ans;
}

线段树

线段树1

传送门:P3372 【模板】线段树 1

操作:

  1. 将某区间每一个数加上 (k)
  2. 求出某区间每一个数的和。

code:

void build(ll u, ll l, ll r) {
	if(l == r) {
		tre[u].sum = read();
		return ;
	}
	ll lson = u << 1, rson = (u << 1) + 1, mid = (l + r) >> 1;
	build(lson, l, mid); build(rson, mid + 1, r);
	tre[u].sum = tre[lson].sum + tre[rson].sum;
}

void pushdown(ll u, ll l, ll r) {
	if(tre[u].lazy == 0 || l == r) return;
	ll lson = (u << 1), rson = (u << 1) + 1, mid = (l + r) >> 1;
	tre[lson].lazy += tre[u].lazy; tre[lson].sum = tre[lson].sum + tre[u].lazy * (mid - l + 1);
	tre[rson].lazy += tre[u].lazy; tre[rson].sum = tre[rson].sum + tre[u].lazy * (r - mid);
	tre[u].lazy = 0;
}

void update(ll u, ll l, ll r, ll x, ll y, ll k) {
	if(l >= x && r <= y) {
		tre[u].lazy = tre[u].lazy + k;
		tre[u].sum = tre[u].sum + k * (r - l + 1);
		return ;
	}
	ll lson = u << 1, rson = (u << 1) + 1, mid = (l + r) >> 1;
	pushdown(u, l, r);
	if(x <= mid) update(lson, l, mid, x, y, k);
	if(y > mid) update(rson, mid + 1, r, x, y, k);
	tre[u].sum = tre[lson].sum + tre[rson].sum;
}

ll query(ll u, ll l, ll r ,ll x, ll y) {
	if(l >= x && r <= y) return tre[u].sum;
	ll lson = u << 1, rson = (u << 1) + 1, mid = (l + r) >> 1, t1 = 0, t2 = 0;
	pushdown(u, l ,r);
	if(x <= mid) t1 = query(lson, l, mid, x, y);
	if(y > mid) t2 = query(rson, mid + 1, r, x, y);
	return t1 + t2;
}

线段树2

传送门:P3373 【模板】线段树 2

操作:

  1. 将某区间每一个数乘上(x)
  2. 将某区间每一个数加上(x)
  3. 求出某区间每一个数的和

code:

void build(int tre,int l,int r) {
	t[tre].lazy2 = 1;
	if(l == r) {
		t[tre].sum = read() % p;
		return ;
	}
	int mid = (l + r) >> 1;
	build(lson,l,mid); build(rson,mid + 1,r);
	t[tre].sum = (t[lson].sum + t[rson].sum) % p;
}

void pushdown(int tre,int l,int r) {
	int mid = (l + r) >> 1;
	t[lson].lazy1 = (t[lson].lazy1 * t[tre].lazy2 + t[tre].lazy1) % p;
	t[rson].lazy1 = (t[rson].lazy1 * t[tre].lazy2 + t[tre].lazy1) % p;
	t[lson].lazy2 = (t[lson].lazy2 * t[tre].lazy2) % p;
	t[rson].lazy2 = (t[rson].lazy2 * t[tre].lazy2) % p;
	t[lson].sum = ((t[lson].sum * t[tre].lazy2) % p + (t[tre].lazy1 * (mid - l + 1)) % p) % p;
	t[rson].sum = ((t[rson].sum * t[tre].lazy2) % p + (t[tre].lazy1 * (r - mid)) % p) % p;
	t[tre].lazy1 = 0; t[tre].lazy2 = 1;
}

void updata1(int tre,int l,int r,int x,int y,int z) {
	if(l >= x && r <= y) {
		t[tre].sum = (t[tre].sum + (r - l + 1) * z) % p;
		t[tre].lazy1 = (t[tre].lazy1 + z) % p;
		return ;
	}
	pushdown(tre,l,r);
	int mid = (l + r) >> 1;
	if(x <= mid) updata1(lson,l,mid,x,y,z);
	if(y > mid) updata1(rson,mid + 1,r,x,y,z);
	t[tre].sum = (t[lson].sum + t[rson].sum) % p;
}

void updata2(int tre,int l,int r,int x,int y,int z) {
	if(l >= x && r <= y) {
		t[tre].sum = (t[tre].sum * z) % p;
		t[tre].lazy1 = (t[tre].lazy1 * z) % p;
		t[tre].lazy2 = (t[tre].lazy2 * z) % p;
		return ;
	}
	pushdown(tre,l,r);
	int mid = (l + r) >> 1;
	if(x <= mid) updata2(lson,l,mid,x,y,z);
	if(y > mid) updata2(rson,mid + 1,r,x,y,z);
	t[tre].sum = (t[lson].sum + t[rson].sum) % p;
}

int query(int tre,int l,int r,int x,int y) {
	if(l >= x && r <= y) return t[tre].sum;
	pushdown(tre,l,r);
	int mid = (l + r) >> 1,t1 = 0,t2 = 0;
	if(x <= mid) t1 = query(lson,l,mid,x,y);
	if(y > mid) t2 = query(rson,mid + 1,r,x,y);
	return (t1 + t2) % p;
}
原文地址:https://www.cnblogs.com/aurorapolaris/p/13449104.html