zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    设计模式学习
    rabbitMQ topic实现广播
    rabbitMQ direct实现广播
    rabbitMQ fanout 实现广播
    rabbitMQ 生产者消费者
    python select 实现IO异步
    python gevent 爬虫
    python gevent socket
    python 协程
    python 进程池
  • 原文地址:https://www.cnblogs.com/aurorapolaris/p/13449104.html
Copyright © 2011-2022 走看看