模板(出锅了望周知,感谢)

顺序大致按照luogu模板题排列

spfa判负环

#include<cstdio>
#include<queue>
using namespace std;
const int N = 2000+99;
const int M = 3000+99;
const int INF = 2147000047;

int n, m, T;
struct edge{
	int y, nxt, val;
}e[M<<1];
int head[N], cnt;
void add_edge(int x, int y, int val) {
	e[++cnt].y = y;
	e[cnt].val = val;
	e[cnt].nxt = head[x];
	head[x] = cnt;
}

int vis[N], dis[N], num[N];
queue<int> q;
int spfa() {
	for(int i = 1; i <= n; i++) vis[i] = num[i] = 0, dis[i] = INF;
	dis[1] = 0;
	q.push(1);
	vis[1] = 1;
	while(!q.empty()) {
		int now = q.front(); q.pop();
		vis[now] = 0;
		for(int i = head[now]; i; i = e[i].nxt) if(dis[e[i].y] > dis[now]+e[i].val){
			dis[e[i].y] = dis[now] + e[i].val;
			if(!vis[e[i].y]) {
				q.push(e[i].y); vis[e[i].y] = 1;
				if(++num[e[i].y] > n) return false;
			}
		}
	}
	return true;
}

void init() {
	cnt = 0;
	for(int i = 1; i <= n; i++) head[i] = 0;
}

int main() {
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d", &n, &m);
		int x, y, val;
		for(int i = 1; i <= m; i++) {
			scanf("%d%d%d", &x, &y, &val);
			add_edge(x, y, val);
			if(val >= 0) add_edge(y, x, val);
		}
		if(!spfa()) printf("YE5
");
		else printf("N0
");
		init();
	}
}

st

#include<bits/stdc++.h>
using namespace std;

int n,m;
int st[100000+99][17];

int RMQ(int l, int r) {
	int k = 0;
	while(1<<(k+1) <= r-l+1) k++;
	return max(st[l][k], st[r -(1<<k)+1][k]);
}

int main() {
	scanf("%d%d",&n, &m);
	for(int i = 1; i <= n; i++) scanf("%d",&st[i][0]);
	for(int k = 1; (1<<k) <= n; k++) 
		for(int i = 1; i + (1<<k) - 1 <= n; i++) 
			st[i][k] = max(st[i][k-1], st[i+(1<<(k-1) )][k-1]);
	int l,r;
	for(int i = 1; i <= m; i++) {
		scanf("%d%d", &l, &r);
		printf("%d
",RMQ(l,r));
	}
}

并查集

写太丑了,不发了

乘法逆元:线性求[1,n]的逆

#include<cstdio>
using namespace std;

int n, p;
int inv[3000000+9]; 

int main() {
	scanf("%d%d",&n, &p);
	inv[1] = 1; printf("1
");
	for(int i = 2; i <= n; i++) {
		inv[i] = (long long)(p - p/i)*inv[p%i]%p;
		printf("%d
", inv[i]);
	}
	return 0;
}

裴蜀定理

#include<cstdio>
#include<algorithm>
using namespace std;

int gcd(int x, int y) {
	return !y ? x : gcd(y, x%y);
}

int n, ans;
int tmp;

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) {
		scanf("%d", &tmp);
		if(tmp < 0) tmp = -tmp;
		ans = gcd(ans, tmp);
	}
	printf("%d", ans);
}

欧拉定理:$ a^bmod m$

#include<cstdio>
#include <iostream>
#include<cmath>
using namespace std;
//#define int long long

int a, b, p;
int read(int m) {
    char ch = getchar(); int x = 0;
    int tag = 0;
    while(ch<'0' || ch>'9') {ch = getchar();}
    while(ch>='0' && ch<= '9') {
        x = (x<<1)+(x<<3)+(ch^48);
        if(x >= m) {
            x %= m;//只需要最后加上phi(p)即可 
            tag = 1;
        }
        ch = getchar();
    }
    if(tag) x += m;//只有x>=phi时才x+=phi
    return x;
}

int ksm(int a, int b, int p) {
    int ans = 1;
    while(b) {
        if(b&1) ans = (long long)ans*a%p;
        b >>= 1;
        a = (long long)a*a%p;
    }
    return ans;//?
}

int el_phi(int x) {
    int m = sqrt(x+0.5), ans = x;
    for(int i = 2; i <= m; i++) if(x%i == 0) {
        ans = ans/i*(i-1);
        while(x%i == 0) x /= i;
    }
    if(x > 1) ans = ans/x*(x-1);
    return ans; 
}

signed main() {
//  freopen("testdata (4).in", "r", stdin);
//  freopen("testdata (4).out", "w", stdout);
    scanf("%d%d", &a, &p);
    a %= p;
    b = read(el_phi(p));
    printf("%d
", ksm(a, b, p));
}

线段树

//出错了请告知,感谢!

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100000+99;

struct tree{
	long long add, sum, mx, set;
}tr[N<<2];

long long a[N];
void pushup(int o) {
	tr[o].mx = max(tr[o<<1].mx, tr[o<<1|1].mx);
	tr[o].sum = tr[o<<1].sum + tr[o<<1|1].sum;
}
void build(int o, int l, int r) {
	tr[o].add = 0; tr[o].set = -1;
	if(l == r) {
		tr[o].sum = tr[o].mx = a[l];
		return ;
	}
	int mid = (l+r)>>1;
	build(o<<1, l, mid);
	build(o<<1|1, mid+1, r);
	pushup(o);
}
void pushdown(int o, int l, int r) {
	int mid = (l+r)>>1;
	if(tr[o].set != -1) {
		tr[o<<1].set = tr[o<<1|1].set = tr[o<<1].mx = tr[o<<1|1].mx = tr[o].set;
		tr[o<<1].add = tr[o<<1|1].add = 0;
		tr[o<<1].sum = tr[o].set*(mid-l+1); tr[o<<1|1].sum = tr[o].set*(r-mid);
		tr[o].set = -1;
	}
	if(tr[o].add) {
		tr[o<<1].add += tr[o].add; tr[o<<1|1].add += tr[o].add;
		tr[o<<1].sum += tr[o].add*(mid-l+1); tr[o<<1|1].sum += tr[o].add*(r-mid);
		tr[o<<1].mx += tr[o].add; tr[o<<1|1].mx += tr[o].add;
		tr[o].add = 0;
	}
}
void optadd(int o, int l, int r, int ql, int qr, long long k) {
	if(ql <= l && r <= qr) {
		tr[o].sum += k*(r-l+1);
		tr[o].add += k;
		tr[o].mx += k;
		return ;
	}
	int mid = (l+r)>>1;
	pushdown(o, l, r);
	if(ql <= mid) optadd(o<<1, l, mid, ql, qr, k);
	if(mid < qr) optadd(o<<1|1, mid+1, r, ql, qr, k);
	pushup(o);
}
void optset(int o, int l, int r, int ql, int qr, long long k) {
	if(ql <= l && r <= qr) {
		tr[o].set = tr[o].mx = k;
		tr[o].add = 0;
		tr[o].sum = k*(r-l+1);
		return ;
	}
	int mid = (l+r)>>1;
	pushdown(o, l, r);
	if(ql <= mid) optset(o<<1, l, mid, ql, qr, k);
	if(mid < qr) optset(o<<1|1, mid+1, r, ql, qr, k);
	pushup(o);
}
long long query_sum(int o, int l, int r, int ql, int qr) {
	if(ql <= l && r <= qr) return tr[o].sum;
	int mid = (l+r)>>1;
	pushdown(o, l, r);
	long long ans = 0;
	if(ql <= mid) ans += query_sum(o<<1, l, mid, ql, qr);
	if(mid < qr) ans += query_sum(o<<1|1, mid+1, r, ql, qr);
	return ans;
}
long long query_mx(int o, int l, int r, int ql, int qr) {
	if(ql <= l && r <= qr) return tr[o].mx;
	int mid = (l+r)>>1;
	pushdown(o, l, r);
	long long mx = -2147000047;
	if(ql <= mid) mx = max(mx, query_mx(o<<1, l, mid, ql, qr));
	if(mid < qr) mx = max(mx, query_mx(o<<1|1, mid+1, r, ql, qr));
	return mx;
}

int n, m;

int main() {
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
	build(1, 1, n);
	int cmd, x, y;
	long long k;
	for(int i = 1; i <= m; i++) {
		scanf("%d", &cmd);
		if(cmd == 1) {
			scanf("%d%d%lld", &x, &y, &k);
			optadd(1, 1, n, x, y, k);
		}else {
			scanf("%d%d", &x, &y);
			printf("%lld
", query_sum(1, 1, n, x, y));
		}
	}
}

模板二不想打了2333...

树链剖分

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100000+99;

int n, m, s, p;
struct node{
	int dep, size, fa, son, tp, in, out;
}a[N];

struct edge{
	int y, nxt;
}e[N<<1];
int head[N], cnt;
void add_edge(int x, int y) {
	e[++cnt].y = y;
	e[cnt].nxt = head[x];
	head[x] = cnt;
}

void dfs1(int x, int fa) {
	a[x].dep = a[fa].dep + 1;
	a[x].size = 1;
	a[x].fa = fa;
	for(int i = head[x]; i; i = e[i].nxt) if(e[i].y != fa) {
		dfs1(e[i].y, x);
		a[x].size += a[e[i].y].size;
		a[x].son = a[a[x].son].size > a[e[i].y].size ? a[x].son : e[i].y;
	}
}
int _clock, pos[N], b[N];
void dfs2(int x, int tp) {
	a[x].tp = tp;
	a[x].in = ++_clock;
	pos[_clock] = b[x];
	if(a[x].son) dfs2(a[x].son, tp);
	for(int i = head[x]; i; i = e[i].nxt) if(e[i].y != a[x].fa && e[i].y != a[x].son) 
		dfs2(e[i].y, e[i].y);
	a[x].out = _clock;
}

struct tree{
	int sum, add;
}tr[N<<2];
void pushup(int o) {tr[o].sum = (tr[o<<1].sum + tr[o<<1|1].sum)%p;}
void build(int o, int l, int r) {
	tr[o].add = 0;
	if(l == r) {
		tr[o].sum = pos[l]%p;
		return ;
	}
	int mid = (l+r)>>1;
	build(o<<1, l, mid);
	build(o<<1|1, mid+1, r);
	pushup(o);
}
void pushdown(int o, int l, int r) {
	if(!tr[o].add) return ;
	tr[o<<1].add = (tr[o<<1].add + tr[o].add)%p; 
	tr[o<<1|1].add = (tr[o<<1|1].add + tr[o].add)%p;
	int mid = (l+r)>>1;
	tr[o<<1].sum = (tr[o<<1].sum + tr[o].add*(mid-l+1) )%p; 
	tr[o<<1|1].sum = (tr[o<<1|1].sum + tr[o].add*(r-mid) )%p;
	tr[o].add = 0;
}
void optadd(int o, int l, int r, int ql, int qr, int k) {
	if(ql <= l && r <= qr) {
		tr[o].add = (tr[o].add + k)%p;
		tr[o].sum = (tr[o].sum + k*(r-l+1))%p;
		return ;
	}
	int mid = (l+r)>>1;
	pushdown(o, l, r);
	if(ql <= mid) optadd(o<<1, l, mid, ql, qr, k);
	if(mid < qr) optadd(o<<1|1, mid+1, r, ql, qr, k);
	pushup(o);
}
int query(int o, int l, int r, int ql, int qr) {
	if(ql <= l && r <= qr) return tr[o].sum;
	int mid = (l+r)>>1;
	pushdown(o, l, r);
	int ans = 0;
	if(ql <= mid) ans = (ans + query(o<<1, l, mid, ql, qr))%p;
	if(mid < qr) ans = (ans + query(o<<1|1, mid+1, r, ql, qr))%p;
	return ans;
}

void ttt_optadd(int x, int y, int k) {
	while(a[x].tp != a[y].tp) {
		if(a[a[x].tp].dep < a[a[y].tp].dep) swap(x, y);
		optadd(1, 1, _clock, a[a[x].tp].in, a[x].in, k);
		x = a[a[x].tp].fa;
	}
	if(a[x].dep > a[y].dep) swap(x, y);
	optadd(1, 1, _clock, a[x].in, a[y].in, k);
}
int ttt_query(int x, int y) {
	int ans = 0;
	while(a[x].tp != a[y].tp) {
		if(a[a[x].tp].dep < a[a[y].tp].dep) swap(x, y);
		ans = (ans + query(1, 1, _clock, a[a[x].tp].in, a[x].in))%p;
		x = a[a[x].tp].fa;
	}
	if(a[x].dep > a[y].dep) swap(x, y);
	ans = (ans + query(1, 1, _clock, a[x].in, a[y].in))%p;
	return ans;
}
int main() {
//	freopen("testdata.in", "r", stdin);
	scanf("%d%d%d%d", &n, &m, &s, &p);
	for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
	int x, y;
	for(int i = 1; i < n; i++) {
		scanf("%d%d", &x, &y);
		add_edge(x, y);
		add_edge(y, x);
	}
	dfs1(s, 0);
	dfs2(s, s);
	build(1, 1, _clock);
	int cmd, z;
	for(int i = 1; i <= m; i++) {
		scanf("%d", &cmd);
		if(cmd == 1) {
			scanf("%d%d%d",&x, &y, &z);
			ttt_optadd(x, y, z);
		}else if(cmd == 2) {
			scanf("%d%d",&x, &y);
			printf("%d
", ttt_query(x, y));
		}else if(cmd == 3) {
			scanf("%d%d",&x, &z);
			optadd(1, 1, _clock, a[x].in, a[x].out, z);
		}else {
			scanf("%d", &x);
			printf("%d
", query(1, 1, _clock, a[x].in, a[x].out));
		}
	}
}

树状数组

#include<cstdio>
#define lowbit(x) (x & -x)
#define MAX 11111
int n,m;
int t[MAX],a[MAX];//t为树状数组

void add(int x, int k) {//单点修改(向树上走)
    for(int i = x; i <= n; i += lowbit(i)) {
        t[i] += k;
    }
}

int query(int x) {//区间查询(在树下向前推进)//求的是前缀和
    int sum = 0;
    for(int i = x; i; i -= lowbit(i)) {
        sum += t[i];
    }
    return sum;
}

void lineplus(const int & l , const int &r, const int &k) {
    add(l , k);
    add(r + 1 , -k);
} //区间修改 & 单点查询 //将区间l~~r的值加k , 要在差分数组中做 ,此时a为差分数组 

int main() {
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; i++) {
        scanf("%d",&a[i]);
        add(i , a[i]);
        //add(i, a[i] - a[i-1]) //差分 
    }
    int x,y;
    for(int i = 1; i <= m; i++) {
        scanf("%d%d",&x,&y);
        printf("%d
",query(y) - query(x - 1));//求的是区间和(x~~y)
    }
/*  int k;
    scanf("%d%d%d",&x,&y,&k);
    lineplus(x,y,k);//x~~y区间加k
    
    scanf("%d",&x) 
    printf("%d",queue(x) );//查询单点x //差分得出的t的前缀和 
*/
}

luogu乘法逆元2(应该不算模板)

#include<cstdio>
using namespace std;//5000009
#pragma GCC optimize(3,"Ofast","inline")
inline int read() {
	char ch = getchar(); int x = 0;
	while(ch<'0' || ch>'9') {ch = getchar();}
	while(ch>='0' && ch<='9') {x = (x<<1)+(x<<3)+(ch^48); ch = getchar();}
	return x;
}

int n, p, k;
int qzj[5000009], hzj[5000009], a[5000009];

void exgcd(int a, int b, int& x, int& y) {
	if(!b) {
		x = 1;
		y = 0;
	}
	else exgcd(b, a%b, y, x), y -= (a/b)*x;
}

int main() {
//	freopen("testdata (4).in", "r", stdin);
//	freopen("testdata (4).out", "w", stdout);
	n = read(), p = read(), k = read();
	qzj[0] = 1;//27行,34行有用 
	for(int i = 1; i <= n; i++) {
		a[i] = read();
		qzj[i] = 1ll*qzj[i-1]*a[i]%p;
	}
	int y;
	exgcd(qzj[n], p, hzj[n+1], y);
	for(int i = n; i >= 1; i--) hzj[i] = 1ll*hzj[i+1]*a[i]%p;//hzj[n] = a_{1}^{-1}*...*a_{n-1}^{-1}  
	int ans = 0, tk = k;//tk累乘 
	for(int i = 1; i <= n; i++) {
		ans = (ans+(qzj[i-1]*1ll*hzj[i+1]%p)*tk)%p;//里面的会溢出!! 
		tk = tk*1ll*k%p;
	}
	if(ans < 0) ans = (ans+p)%p;//ans已经是p以内的了  
	printf("%d
", ans);
	return 0;
}

线性筛素数

欧拉筛:

#include<cstdio>
using namespace std;
const int N = 10000000+9;

int not_prime[N] = {1, 1};
int prime[N], tot;
int n, m;

void L_S(){
        phi[1] = 1;
	for(int i = 2; i <= n; i++) {
		if(!not_prime[i]) 
			prime[++tot] = i;
		for(int j = 1; j <= tot && i*prime[j] <= n; j++) {
			not_prime[i*prime[j]] = 1;
			if(!( i%prime[j]) ) break;
		}
	}	
}

int main() {
	scanf("%d%d", &n, &m);
	L_S();
	int x;
	for(int i = 1; i <= m; i++) {
		scanf("%d", &x);
		if(not_prime[x]) printf("No
");
		else printf("Yes
");
	}
}

埃筛:

#include<cstdio>
#include<cmath>
using namespace std; 
#define MAXN 10000000+99
int n,m;
int isp[MAXN];

int main() {
	scanf("%d%d",&n,&m);
//	for(int i = 2; i <= n; i++) 
//		for(int j = i*i; j <= n; j+=i) isp[j] = 1;
	int tmp = sqrt(n+0.5);//说是解决精度问题,不懂... 
	for(int i = 2; i <= tmp; i++) if(!isp[i]) //i*i<n //1看题目考虑 
		for(int j = i*i; j <= n; j+=i) {//没有必要从j*2, 因为在i=2的时候已经被筛掉了 
			isp[j] = 1;
		}
	
	int x;
	for(int i = 1; i <= m; i++) {
		scanf("%d",&x);
		if(x == 1) {
			printf("No
");
			continue;
		}
		if(isp[x] == 0) printf("Yes
");
		else printf("No
");
	}
	
}

求欧拉函数

分解质因数做法

int euler_phi(int n) {
    int m = (int)sqrt(n+0.5);//(还是说解决精度问题//这里都行吧
    int ans =  n;
    for(int i = 2; i <= m; i++) if(n%i == 0) {
        ans = ans / i * (i-1);
        while(n%i == 0) n /= i;
    }
    if(n > 1) ans = ans / n * (n-1);//还要看n有没有大于sqrt(n)的质因数 
}

线性筛法

   int not_prime[N] = {1, 1};
   int prime[N], tot;
   int n, m;
   int phi[N];
   
   void L_S(){
    for(int i = 2; i <= n; i++) {
        if(!not_prime[i]) {
            prime[++tot] = i;
            phi[i] = i - 1;//基本性质2:费马小定理 
        }
        for(int j = 1; j <= tot && i*prime[j] <= n; j++) {
            not_prime[i*prime[j]] = 1;
            if(i % prime[j] == 0) {//如果i是prime的倍数->i与prime[j]不互质 
                phi[i*prime[j]] = phi[i]*prime[j];
                break;
            }
            phi[i*prime[j]] = phi[i]*(prime[j]-1);//互质的时候,左边=phi[i]*phi[prime[j]],即=右边的
        }
    }
   }

最小生成树

不会prim.....

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXM = 200000+9;
const int MAXN = 5000+9;
int n,m,ans;

struct node{
	int x,y,val;
}e[MAXM];

bool cmp(node x, node xx) {
	return x.val < xx.val ;
}

int fa[MAXN];

int dad(int x) {
	if(x == fa[x] ) return fa[x];
	else return fa[x] = dad(fa[x] );
}

int main() {
	scanf("%d%d",&n,&m);
	for(int i = 1; i <= n; i++) fa[i] = i;
	for(int i = 1; i <= m; i++) {
		scanf("%d%d%d",&e[i].x ,&e[i].y ,&e[i].val ) ;	
	}
	sort(e+1, e+1+m, cmp);
	int x,y;
	for(int i = 1; i <= m; i++) {
		x = dad(e[i].x) , y = dad(e[i].y) ;
		if(x != y) {
			fa[x] = fa[y];
			ans += e[i].val ;
		}
	}
	printf("%d",ans);
}

有理数取余: 快读中加取模

//也可以用exgcd之类的

#include<cstdio>
#include<algorithm>
using namespace std;
const int MOD = 19260817;

int read() {
	char ch = getchar(); int x = 0, f = 1;
	while(ch<'0' || ch>'9') {if(ch=='-') f = -1; ch = getchar();}
	while(ch>='0' && ch<='9') {x = ((x<<1)+(x<<3)+(ch^48))%MOD; ch = getchar();}
	return x*f;
}

int a, b;

int qsm(int a, int b, int p) {
	int ans = 1;
	while(b) {
		if(b & 1) ans = (long long)ans*a%p;
		b >>= 1;
		a = (long long)a*a%p;
	}
	return ans%p;
}

int main() {
	a = read(), b = read();
	if(b == 0) {
		printf("Angry!
");
		return 0;
	}
	printf("%lld
", (long long)a*qsm(b, MOD-2, MOD)%MOD);
}

快速幂||取余运算

#include<cstdio>
using namespace std;
#define ll long long

ll a, b, p;
ll ksm(ll a, ll b, ll p) {
	if(a == 0) return 0;
	ll res = 1;
	while(b) {
		if(b&1)	res = (res*a)%p;
		b >>= 1;
		a = (a*a)%p;
	}
	return res%p;
}

int main() {
	scanf("%lld%lld%lld", &a, &b, &p);
	printf("%lld^%lld mod %lld=%lld
", a, b, p, ksm(a, b, p));
	return 0;
} 

建议用上面那个....

下面是刘汝佳书里的

#include<cstdio>
using namespace std;

long long pow_mod(long long a, long long b, long long p) {
	if(!b) return 1;
	long long x = pow_mod(a, b/2, p);
	long long ans = (x%p)*(x%p)%p;
	if(b%2) ans = ans*a%p;
	return ans;
}

long long a, b, p;

int main() {
	scanf("%lld%lld%lld",&a, &b,&p);
	long long ans = pow_mod(a, b, p);
	if(b == 0 && p == 1) ans = 0;
	printf("%lld^%lld mod %lld=%lld
",a, b, p, ans);
}

最长公共子序列

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 100000+9;
const int MAX = N;

int a[N], b[N], map[MAX];
int n;
int f[N];

int main() {
	scanf("%d", &n);
	for(int i = 1; i <= n; i++) scanf("%d", &a[i]), map[a[i]] = i;
	for(int j = 1; j <= n; j++) scanf("%d", &b[j]), a[j] = map[b[j]], f[j] = MAX;
	int len = 1;
	f[1] = a[1];
	for(int i = 2; i <= n; i++) {
		if(a[i] > f[len]) f[++len] = a[i];
		else {
			int l = 1, r = len, mid;
			while(l < r) {
				mid = (l+r)>>1;
				if(f[mid] >= a[i]) r = mid;
				else l = mid + 1;
			}
			f[l] = min(f[l], a[i]);
		}
	}
	printf("%d", len);
	return 0;
}

单源最短路

dijkstra

#include<cstdio>
#include<queue>
using namespace std;
const int N = 100000+9;
const int M = 200000+9;
const int INF = 2147000047;

int n, m, S;
int dis[N], vis[N];

struct node{
	int id, dis;
	node(int id, int dis) : id(id), dis(dis) {}
	bool operator < (const node& xxx) const {
		return dis > xxx.dis;
	}
};

priority_queue <node> q;

struct edge{
	int y, nxt, val;
}e[M];
int head[N], cnt;
void add_edge(int x, int y, int val) {
	e[++cnt].y = y;
	e[cnt].val = val;
	e[cnt].nxt = head[x];
	head[x] = cnt;
}

void dijkstra() {
	for(int i = 1; i <= n; i++) dis[i] = INF;
	dis[S] = 0;
	q.push(node(S, dis[S]));
	while(!q.empty()) {
		node tmp = q.top(); q.pop();
		int now = tmp.id;
		if(vis[now]) continue;
		vis[now] = 1;
		for(int i = head[now]; i; i = e[i].nxt) {
			if(dis[e[i].y] > tmp.dis + e[i].val) {
				dis[e[i].y] = tmp.dis + e[i].val;
				q.push(node(e[i].y, dis[e[i].y]));
			}
		}
	}
}

int main() {
	scanf("%d%d%d",&n, &m, &S);
	int x, y, val;
	for(int i = 1; i <= m; i++) {
		scanf("%d%d%d",&x,&y,&val);
		add_edge(x, y, val);
	}
	dijkstra();
	for(int i = 1; i <= n; i++) printf("%d ", dis[i]);
}

spfa

#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int N = 10000+99;
const int M = 500000+99;
const int INF = 2147483647;

int n, m, s;
struct edge{
	int y, val, nxt;
}e[M];
int head[N], cnt;
void add_edge(int x, int y, int val) {
	e[++cnt].y = y;
	e[cnt].val = val;
	e[cnt].nxt = head[x];
	head[x] = cnt;
}

int dis[N], vis[N];
queue<int> q;

void spfa() {
	for(int i = 1; i <= n; i++) dis[i] = INF, vis[i] = 0;
	dis[s] = 0;
	vis[s] = 1;
	q.push(s);
	while(!q.empty()) {
		int now = q.front(); q.pop();
		vis[now] = 0;
		for(int i = head[now]; i; i = e[i].nxt) if(dis[e[i].y] > dis[now] + e[i].val) {
			dis[e[i].y] = dis[now] + e[i].val;
			if(!vis[e[i].y]) q.push(e[i].y), vis[e[i].y] = 1;
		}
	}
}

int main() {
	scanf("%d%d%d", &n, &m, &s);
	int x, y, val;
	for(int i = 1; i <= m; i++) {
		scanf("%d%d%d", &x, &y, &val);
		add_edge(x, y, val);
	}
	spfa();
	for(int i = 1; i <= n; i++) printf("%d ", dis[i]);
	return 0;
}

高精度

数组版

#include<cstdio>
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
const int N = 100000;

int a[N], b[N], c[N], lena, lenb, lenc;
string x, y;

void jinwei() {
    for(int i = 1; i <= lenc; i++) if(c[i] >= 10) {
        c[i+1] += c[i]/10;
        c[i] %= 10;
        if(i == lenc) lenc++;
    }
    while(lenc && c[lenc] == 0) lenc--;//保证lenc不为负 
}

int main() {
    cin>>x>>y;
    lena = x.length(), lenb = y.length();
    /*if(lena < lenb || (lena==lenb && x < y)) {//减法时使用 
        swap(x, y);
        swap(lena, lenb);//保证a>=b 
        printf("-");
    }*/
    for(int i = 0; i < lena; i++) a[lena-i] = x[i]-'0';
    for(int i = 0; i < lenb; i++) b[lenb-i] = y[i]-'0';
//  for(int i = lena; i >= 1; i--) printf("%d", a[i]);
//  printf("
");
//  for(int i = lenb; i >= 1; i--) printf("%d", b[i]);
//  printf("
");
    
//高精加: 非负数相加 
/*  lenc = max(lena, lenb);
    for(int i = 1; i <= lenc; i++) c[i] = a[i]+b[i];
    jinwei();*/
    
//高精减 
/*  for(int i = 1, j = 1; i <= lena || j <= lenb; i++, j++) {
        if(a[i] < b[i]) {a[i] += 10; --a[i+1];}
        c[i] = a[i] - b[i];
    }
    lenc = lena;
    while(c[lenc] == 0 && lenc) lenc--;//注意使lenc不为负 */
    
//高精乘
/*  for(int i = 1; i <= lena; i++) 
        for(int j = 1; j <= lenb; j++) 
            c[i+j-1] += a[i]*b[j]; 
    lenc = lena+lenb-1;
    jinwei();*/ 
    if(lenc == 0) printf("0");
    else for(int i = lenc; i > 0; i--)  printf("%d", c[i]);
    return 0;
}
//高精除低精 
/*  for(int i = lena; i >= 1; i--) {
        a[i-1] += (a[i]%k)*10;
        a[i] = a[i]/k;
    }
    while(a[lena] == 0 && lena) lena--;
    if(lena == 0) printf("0");
    else for(int i = lena; i >= 1; i--) printf("%d", a[i]);*/
//高精%低精 
/*  int yushu = 0;
    for(int i = lena; i >= 1; i--) {
        yushu = yushu*10+a[i];
        yushu %= k;
    } 
    printf("%d", yushu);*/

结构体版高精度

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
using namespace std;
const int N = 1000000;//共几位(乘法时使用 
int C[N];

struct BigInteger {
    static const int BASE = 10000;
    static const int WIDTH = 4;//记得修改压位的时候,下面重载“<<”中的sprintf处也要修改
    vector<int> s;
    void cr() {//去除前导0 
        while(s.size() && s.back() == 0) s.pop_back();
        return ;
    }

    BigInteger(long long num = 0) { *this = num; }// 构造函数
    BigInteger operator = (long long num) { // 赋值运算符
        s.clear();
        do {
            s.push_back(num % BASE);
            num /= BASE;
        } while(num > 0);
        return *this;
    }
    BigInteger(const string& str) {*this = str;}   // 构造函数
    BigInteger operator = (const string& str) { // 赋值运算符
        s.clear();
        int x, len = (str.length() - 1) / WIDTH + 1;
        for(int i = 0; i < len; i++) {
            int end = str.length() - i*WIDTH;//stl左闭右开
            int start = max(0, end - WIDTH);//“开着的右”-“真实长度”=“闭着的左”
            sscanf(str.substr(start, end-start).c_str(), "%d", &x);
            //str.substr(start, len): 从string类型的str中,截取以start为左端点,长度为len的string
            //str.c_str(): 把string类型的str转化成数组??//这两个我也没仔细查,以后会补上的
            s.push_back(x);
        }
        return *this;
    }

    BigInteger operator + (const BigInteger& b) const {//重载运算符
        BigInteger c;
        c.s.clear();
        for(int i = 0, g = 0; g != 0 || i < s.size() || i < b.s.size(); i++) {
            int x = g;//g表示进位数
            if(i < s.size()) x += s[i];
            if(i < b.s.size()) x += b.s[i];
            c.s.push_back(x % BASE);
            g = x / BASE;
        }
        c.cr();
        return c;
    }
    BigInteger operator - (const BigInteger& b) const {//s > b.s时使用
        BigInteger c;
        c.s.clear();
        for(int i = 0, y = 0; y != 0 || i < s.size(); i++) {
            int x = s[i]-y;//y表示余数
            y = 0;
            if(i < b.s.size()) x -= b.s[i];
            if(x < 0) x += BASE, y = 1;
            c.s.push_back(x % BASE);
        }
        c.cr();
        return c;
    }

    bool operator < (const BigInteger& b) const {
        if(s.size() != b.s.size()) return s.size() < b.s.size();
        for(int i = s.size() - 1; i >= 0; i--) if(s[i] != b.s[i]) return s[i] < b.s[i];
        return false;//相等
    }
    
    BigInteger operator * (const BigInteger& b) const {
        int lenc = s.size()+b.s.size();
        for(int i = 0; i < lenc; i++) C[i] = 0;//记得清0 
        for(int i = 0; i < s.size(); i++) 
            for(int j = 0; j < b.s.size(); j++){
                C[i+j] += s[i]*b.s[j];
                C[i+j+1] += C[i+j]/BASE;
                C[i+j] %= BASE;
            }
        BigInteger c; c.s.clear();//把已压位的C数组放进struct c 
        while(C[lenc-1] == 0) --lenc;
        for(int i = 0; i < lenc; i++) c.s.push_back(C[i]);
//      c.cr();//上面已经删去前导0了 
        return c;
    }
};

ostream& operator << (ostream &out,const BigInteger& x) {
    out << x.s.back();
    for(int i = x.s.size()-2; i >= 0; i--) {
        char buf[20];
        sprintf(buf, "%04d", x.s[i]);
        for(int j = 0; j < strlen(buf); j++) out << buf[j];
    }
    return out;
}

istream& operator >> (istream &in, BigInteger& x) {
    string s;
    if(!(in >> s)) return in;
    x = s;
//  x.cr();//在这不加时,运算并不会出错,但直接输入输出会有点问题
    return in;
}

//#include<set>
//#include<map>
//set<BigInteger> s;
//map<BigInteger, int> m;

int main() {
    BigInteger a, b;
    cin>>a>>b;
//  if(a < b) { printf("-"); swap(a, b);} //减法
//  cout<<a-b;
    
//  cout<<a+b; //加法
 
    cout<<a*b; //乘法(不能压8位, 会溢出,建议压4位 
    return 0;
}

LCA

树链剖分做法

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 500000+99;
const int MAXM = MAXN<<1;

int n,m,s;
int cnt, head[MAXN];
struct node{
	int tp, size, fa, son, deep, in/*, out*/;
	//top, size,它爸, 重儿子 , 深度 , dfs序 
}a[MAXN];
int clock;

struct seg{
	int y,next;
}e[MAXM];

void add_edge(int x, int y) {
	e[++cnt].y = y;
	e[cnt].next = head[x];
	head[x] = cnt;
}

void dfs1(int x, int fa) {//先找到重儿子 
	a[x].deep = a[fa].deep + 1;
	a[x].size = 1;//包括自己 
	a[x].fa = fa;
	for(int i = head[x]; i; i=e[i].next ) 
		if(e[i].y != fa) {
			dfs1(e[i].y , x);
			a[x].size += a[e[i].y ].size ;
			a[x].son = a[a[x].son ].size > a[e[i].y].size ? a[x].son : e[i].y ;
		}
}

void dfs2(int x, int tp) {//再找top 
//	a[x].in = ++clock;
	a[x].tp = tp;
	if(a[x].son ) dfs2(a[x].son , tp);//如果有重儿子要先dfs重儿子(叶子节点木有?? 
	for(int i = head[x]; i; i = e[i].next ) 
		if(e[i].y != a[x].son && e[i].y != a[x].fa ) //注意判断是不是重儿子(没必要dfs)和祖先(不能dfs) 
			dfs2(e[i].y , e[i].y );
}

int lca(int l, int r) {
	while(a[l].tp != a[r].tp ) {
		if(a[a[l].tp].deep  < a[a[r].tp ].deep ) swap(l, r);
		l = a[a[l].tp].fa ;
	}
	return a[l].deep < a[r].deep ? l : r;
} 

int main() {
	scanf("%d%d%d",&n,&m,&s);
	int x,y;
	for(int i = 1; i < n; i++) {
		scanf("%d%d",&x, &y);
		add_edge(x, y);
		add_edge(y, x);
	}
	dfs1(s, s);
	dfs2(s, s);
	for(int i = 1; i <= m; i++) {
		scanf("%d%d",&x, &y);
		printf("%d
",lca(x, y));
	}
}

背包

网上有很多,麻烦同学们自己找

(其实我没写233...)

原文地址:https://www.cnblogs.com/tyner/p/11861454.html