顺序大致按照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...)