算法模板

算法模板

1.排序

(1)快速排序(No STL)

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,a[100010];

void dfs(int l,int r)
{
	if(l >= r)
		return ;
	int pos = (l + r) >> 1;
	int x = a[pos];
	int i = l,j = r;
	while(i <= j)
	{
		while(a[i] < x)
			i++;
		while(a[j] > x)
			j--;
		if(i <= j)
			swap(a[i],a[j]),i++,j--;
	}
	dfs(l,j);
	dfs(i,r);
}

signed main()
{
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> a[i];
	dfs(1,n);
	for(int i = 1; i <= n; i++)
		cout << a[i] << " ";
	cout << "\n";
	return 0;
}

(2)合并排序

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,a[500010],b[500010],ans = 0;

void merge_sort(int l,int r)
{
	if(l >= r)
		return ;
	int now = l - 1;
	int mid = (l + r) >> 1;
	merge_sort(l,mid);
	merge_sort(mid + 1,r);
	int i = l,j = mid + 1;
	while(i <= mid && j <= r)
	{
		if(a[i] <= a[j])
			b[++now] = a[i],i++;
		else
			b[++now] = a[j],j++,ans += mid - i + 1; // ans表示逆序对数量
	}
	while(i <= mid)
		b[++now] = a[i],i++;
	while(j <= r)
		b[++now] = a[j],j++;
	for(int i = l; i <= r; i++)
		a[i] = b[i];
}

signed main()
{
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> a[i];
	merge_sort(1,n);
	//输出....
	return 0;
}

2.二分

(1)整数三分

int l = ...,r = ...,ans = ...;
while(r - l >= 3)
{
	int m1 = l + (r - l) / 3;
	int m2 = r - (r - l) / 3;
	if(f(m1) > f(m2))
		ans = l,l = m1 + 1;
	else
		r = m2 - 1;
}
while(l <= r)
{
	if(f(l) < f(ans))
		ans = l;
	l++;
}

(2)小数三分

double l = ...,r = ...;
while(l + eps < r)
{
	double m1 = (l + l + r) / 3.0;
	double m2 = (l + r + r) / 3.0;
	if(check(m1) < check(m2))
		r = m2;
	else
		l = m1;
}

然后答案是check(l)或者l

(其中的eps根据题目中要求的精度来定)

(3)二分

int l = ...,r = ...,ans = 0;
while(l <= r)
{
	int mid = (l + r) / 2;
	if(check(mid))
		ans = mid,r = mid - 1;
	else
		l = mid + 1;
}

3.表达式

(1)中缀表达式转后缀表达式并计算及输出过程

#include <bits/stdc++.h>
using namespace std;
#define int long long
string st;
int top = 0,lf[210],rt[210],num[210],cnt = 0,pd[210],tot = 0,d[210],sk[210];
char op[210];

void solve(int x,int l,int r)
{
	if(l == r)
	{
		num[x] = st[l] - '0';
		return ;
	}
	int p = -1,q = -1,t = -1;
	for(int i = l; i <= r; i++)
	{
		if(st[i] == '(')
			i = pd[i];
		else if(st[i] == '+' || st[i] == '-')
			p = i;
		else if(st[i] == '*' || st[i] == '/')
			q = i;
		else if(st[i] == '^' && t == -1)
			t = i;
	}
	if(p == -1)
		p = q;
	if(p == -1)
		p = t;
	if(p == -1)
		solve(x,l + 1,r - 1);
	else
	{
		op[x] = st[p];
		lf[x] = ++cnt;
		solve(lf[x],l,p - 1);
		rt[x] = ++cnt;
		solve(rt[x],p + 1,r);
	}
}

void dfs(int x)
{
	if(lf[x])
		dfs(lf[x]);
	if(rt[x])
		dfs(rt[x]);
	d[++tot] = x;
}

void out(int y)
{
	for(int i = 1; i <= top; i++)
		cout << sk[i] << " ";
	for(int i = y; i <= tot; i++)
	{
		if(lf[d[i]] == 0)
			cout << num[d[i]] << " ";
		else
			cout << op[d[i]] << " ";
	}
	cout << "\n";
}

int qp(int x,int y)
{
	int sum = 1;
	while(y > 0)
	{
		if(y & 1)
			sum *= x;
		x *= x;
		y >>= 1;
	}
	return sum;
}

signed main()
{
	cin >> st;
	for(int i = 0; i < st.length(); i++)
	{
		if(st[i] == '(')
			sk[++top] = i;
		else if(st[i] == ')')
			pd[sk[top]] = i,top--;
	}
	cnt = 1;
	solve(1,0,st.length() - 1);
	dfs(1);
	out(1);
	for(int i = 1; i <= tot; i++)
	{
		if(lf[d[i]] == 0)
			sk[++top] = num[d[i]];
		else
		{
			int y = sk[top--],x = sk[top--],z;
			switch(op[d[i]])
			{
				case '+' : z = x + y; break;
				case '-' : z = x - y; break;
				case '*' : z = x * y; break;
				case '/' : z = x / y; break;
				case '^' : z = qp(x,y); break;
			}
			sk[++top] = z;
			out(i + 1);
		}
	}
	return 0;
}

4.RMQ与ST表

(1)普通模板,min和max可改

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m,p[100010][20];

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

signed main()
{
	n = read(),m = read();
	for(int i = 1; i <= n; i++)
		p[i][0] = read();
	for(int j = 1; (1 << j) <= n; j++)
	{
		for(int i = 1; i + (1 << j - 1) <= n; i++)
			p[i][j] = max(p[i][j - 1],p[i + (1 << j - 1)][j - 1]);
	}
	while(m--)
	{
		int l,r;
		l = read(),r = read();
		int t = log2(r - l + 1);
		cout << max(p[l][t],p[r - (1 << t) + 1][t]) << "\n";
	}
	return 0;
}

(2)log2函数的数组预处理

for(int i = 2; i <= 最大范围; i++)
	lg[i] = lg[i >> 1] + 1;

使用:lg[数字]

(3)在末尾添加数字后更新ST表

p[++n][0] = x;
for(int j = 1; n - (1 << j) + 1 > 0; j++)
	p[n - (1 << j) + 1][j] = max(p[n - (1 << j) + 1][j - 1],p[n - (1 << j - 1) + 1][j - 1]);

5.并查集

(1)普通模板

#include <bits/stdc++.h>
using namespace std;
#define int long long
int f[10010];

int find(int x)
{
    if(f[x] == x)
        return x;
    return f[x] = find(f[x]);
}

void merge(int x,int y)
{
    int f1 = find(x),f2 = find(y);
    f[f1] = f2;
}

signed main()
{
    int n,m;
    cin >> n >> m;
    iota(f + 1,f + n + 1,1);
    for(int i = 1; i <= m; i++)
    {
        int z,x,y;
        cin >> z >> x >> y;
        if(z == 1)
            merge(x,y);
        else
        {
            int f1 = find(x),f2 = find(y);
            if(f1 == f2)
                cout << "Y" << "\n";
            else
                cout << "N" << "\n";
        }
    }
    return 0;
}

6.最短路

(1)Floyd多源最短路

#include <bits/stdc++.h>
using namespace std;
#define int long long
int dis[210][210];

signed main()
{
	int n,m;
	cin >> n >> m;
	memset(dis,0x3f,sizeof(dis));
	for(int i = 1; i <= m; i++)
	{
		int a,b,c;
		cin >> a >> b >> c;
		dis[a][b] = min(dis[a][b],c);
	}
	for(int i = 1; i <= n; i++)
		dis[i][i] = 0;
	for(int k = 1; k <= n; k++)
	{
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= n; j++)
				dis[i][j] = min(dis[i][j],dis[i][k] + dis[k][j]);
		}
	}
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			if(dis[i][j] < 0x3f3f3f3f)
				cout << dis[i][j] << " ";
			else
				cout << -1 << " ";
		}
		cout << "\n";
	}
	return 0;
}

(2)Dijkstra

#include <bits/stdc++.h>
using namespace std;
#define int long long
int s,dis[100010];
bool vis[100010];
vector<int> v[100010],d[100010];

typedef pair<int,int> P;

void dijkstra()
{
	memset(dis,0x3f,sizeof(dis));
	dis[s] = 0;
	priority_queue<P,vector<P>,greater<P> > q;
	q.push(make_pair(0,s));
	while(!q.empty())
	{
		P tmp = q.top();
		q.pop();
		if(vis[tmp.second])
			continue;
		vis[tmp.second] = true;
		for(int i = 0; i < v[tmp.second].size(); i++)
		{
			int to = v[tmp.second][i];
			if(dis[to] > dis[tmp.second] + d[tmp.second][i])
			{
				dis[to] = dis[tmp.second] + d[tmp.second][i];
				q.push(make_pair(dis[to],to));
			}
		}
	}
}

signed main()
{
	int n,m;
	cin >> n >> m >> s;
	for(int i = 1; i <= m; i++)
	{
		int a,b,c;
		cin >> a >> b >> c;
		v[a].push_back(b);
		d[a].push_back(c);
	}
	dijkstra();
	for(int i = 1; i <= n; i++)
	{
		if(dis[i] < 0x3f3f3f3f)
			cout << dis[i] << " ";
		else
			cout << 2147483647 << " ";
	}
	cout << "\n";
	return 0;
}

(3)Spfa

#include <bits/stdc++.h>
using namespace std;
#define int long long
int s,dis[10010];
bool vis[10010];
vector<int> v[10010],d[10010];

void spfa()
{
	memset(dis,0x3f,sizeof(dis));
	dis[s] = 0;
	vis[s] = true;
	queue<int> q;
	q.push(s);
	while(!q.empty())
	{
		int now = q.front();
		q.pop();
		vis[now] = false;
		for(int i = 0; i < v[now].size(); i++)
		{
			if(dis[v[now][i]] > dis[now] + d[now][i])
			{
				dis[v[now][i]] = dis[now] + d[now][i];
				if(!vis[v[now][i]])
				{
					vis[v[now][i]] = true;
					q.push(v[now][i]);
				}
			}
		}
	}
}

signed main()
{
	int n,m;
	cin >> n >> m >> s;
	for(int i = 1; i <= m; i++)
	{
		int a,b,c;
		cin >> a >> b >> c;
		v[a].push_back(b);
		d[a].push_back(c);
	}
	spfa();
	for(int i = 1; i <= n; i++)
	{
		if(dis[i] < 0x3f3f3f3f)
			cout << dis[i] << " ";
		else
			cout << 2147483647 << " ";
	}
	cout << "\n";
	return 0;
}

(4)Spfa判负环

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m,dis[10010],cnt[10010],cntt = -1,head[10010];
bool vis[10010];
queue<int> q;

struct Node
{
    int to,w,nex;
}e[10010];

void add(int u,int v,int w)
{
    e[++cntt].to = v;
    e[cntt].w = w;
    e[cntt].nex = head[u];
    head[u] = cntt;
}

void spfa()
{
	fill(dis + 1,dis + n + 1,0x3f3f3f3f);
	memset(cnt,0,sizeof(cnt));
	memset(vis,0,sizeof(vis));
	while(!q.empty())
	    q.pop();
    dis[1] = 0;
    vis[1] = true;
    q.push(1);
    while(!q.empty())
    {
        int tmp = q.front();
        q.pop();
        vis[tmp] = false;
        for(int i = head[tmp]; i != -1; i = e[i].nex)
        {
            int v = e[i].to;
            int w = e[i].w;
            if(dis[tmp] + w < dis[v])
            {
                dis[v] = dis[tmp] + w;
                cnt[v] = cnt[tmp] + 1;
                if(cnt[v] >= n)
                {
                    cout << "YES" << "\n";
                    return ;
                }
                if(!vis[v])
                {
                    vis[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    cout << "NO" << "\n";
}

signed main()
{
    int t;
    cin >> t;
    while(t--)
    {
        cntt = -1;
        memset(head,-1,sizeof(head));
	    cin >> n >> m;
	    for(int i = 1; i <= m; i++)
	    {
	    	int u,v,w;
	    	cin >> u >> v >> w;
	    	add(u,v,w);
	    	if(w >= 0)
	    	    add(v,u,w);
	    }
	    spfa();
    }
	return 0;
}

(5)查分约束

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m,head[1000010],cnt = 0,cntt[1000010],dis[1000010];
bool vis[1000010];

struct Node
{
	int to,nex,w;
}e[1000010];

void add(int x,int y,int z)
{
	cnt++;
	e[cnt].to = y;
	e[cnt].nex = head[x];
	e[cnt].w = z;
	head[x] = cnt;
}

void spfa()
{
	fill(dis + 1,dis + n + 2,0x3f3f3f3f);
	memset(cntt,0,sizeof(cntt));
	memset(vis,0,sizeof(vis));
	queue<int> q;
	dis[n + 1] = 0;
	vis[n + 1] = true;
	q.push(n + 1);
	while(!q.empty())
	{
		int tmp = q.front();
		q.pop();
		vis[tmp] = false;
		for(int i = head[tmp]; i; i = e[i].nex)
		{
			int v = e[i].to;
			int w = e[i].w;
			if(dis[tmp] + w < dis[v])
			{
				dis[v] = dis[tmp] + w;
				cntt[v] = cntt[tmp] + 1;
				if(cntt[v] >= n)
				{
					cout << "NO SOLUTION" << "\n";
					exit(0);
				}
				if(!vis[v])
				{
					vis[v] = true;
					q.push(v);
				}
			}
		}
	}
}

signed main()
{
	cin >> n >> m;
	for(int i = 1; i <= m; i++)
	{
		int ii,j,b;
		cin >> ii >> j >> b;
		add(j,ii,b);
	}
	for(int i = 1; i <= n; i++)
		add(n + 1,i,0);
	spfa();
	int mind = 0x3f3f3f3f;
	for(int i = 1; i <= n; i++)
		mind = min(mind,dis[i]);
	for(int i = 1; i <= n; i++)
		cout << dis[i] - mind << "\n";
	return 0;
}

记住就是add(a,b,c)时表示a - b >= -c

7.最小生成树

(1)Kruskal

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m,tot = 0,f[5010],ans = 0,cnt = 0;

struct Node
{
	int u,v,w;
}e[400010];

bool cmp(Node x,Node y)
{
	return x.w < y.w;
}

int find(int x)
{
	if(f[x] == x)
		return x;
	return f[x] = find(f[x]);
}

void merge(int x,int y)
{
	int fx = find(x),fy = find(y);
	if(fx == fy)
		return ;
	f[fx] = fy;
}

bool with(int x,int y)
{
	if(find(x) == find(y))
		return true;
	return false;
}

void kruskal()
{
	for(int i = 1; i <= m; i++)
	{
		int u = e[i].u,v = e[i].v;
		if(with(u,v))
			continue;
		merge(u,v);
		ans += e[i].w;
		if(++cnt == n - 1)
			break;
	}
}

signed main()
{
	cin >> n >> m;
	iota(f + 1,f + n + 1,1);
	for(int i = 1; i <= m; i++)
		cin >> e[i].u >> e[i].v >> e[i].w;
	sort(e + 1,e + m + 1,cmp);
	kruskal();
	if(cnt == n - 1)
		cout << ans << "\n";
	else
		cout << "orz" << "\n";
	return 0;
}

(2)Prim

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,c,x[5010],y[5010],dis[5010];
bool vis[5010];

int cal(int a,int b)
{
	return (x[a] - x[b]) * (x[a] - x[b]) + (y[a] - y[b]) * (y[a] - y[b]);
}

void prim()
{
	memset(dis,0x3f,sizeof(dis));
	dis[1] = 0;
	for(int i = 1; i <= n; i++)
	{
		int to = 0;
		for(int i = 1; i <= n; i++)
		{
			if(!vis[i] && dis[i] < dis[to])
				to = i;
		}
		if(to == 0 || dis[to] == 0x3f3f3f3f)
		{
			cout << -1 << "\n";
			exit(0);
		}
		vis[to] = true;
		for(int j = 1; j <= n; j++)
		{
			if(!vis[j] && j != to)
			{
				if(cal(j,to) >= c)
					dis[j] = min(dis[j],cal(j,to));
			}
		}
	}
}

signed main()
{
	cin >> n >> c;
	for(int i = 1; i <= n; i++)
		cin >> x[i] >> y[i];
	prim();
	int ans = 0;
	for(int i = 1; i <= n; i++)
	{
		if(dis[i] == 0x3f3f3f3f)
		{
			cout << -1 << "\n";
			goto tag;
		}
		ans += dis[i];
	}
	cout << ans << "\n";
	tag:;
	return 0;
}

8.拓扑排序

(1)普通模板

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,head[30010],in[30010],a[30010],cnt = 0,tot = 0;

struct Node
{
	int nex,to;
}e[1000010];

void add(int x,int y)
{
	cnt++;
	e[cnt].nex = head[x];
	e[cnt].to = y;
	head[x] = cnt;
}

void toposort()
{
	priority_queue<int,vector<int>,greater<int> > q;
	for(int i = 1; i <= n; i++)
	{
		if(in[i] == 0)
			q.push(i);
	}
	while(!q.empty())
	{
		int u = q.top();
		q.pop();
		a[++tot] = u;
		for(int i = head[u]; i; i = e[i].nex)
		{
			int v = e[i].to;
			in[v]--;
			if(in[v] == 0)
				q.push(v);
		}
	}
}

signed main()
{
	cin >> n;
	for(int i = 1; i <= n; i++)
	{
		int m;
		cin >> m;
		for(int j = 1; j <= m; j++)
		{
			int y;
			cin >> y;
			add(i,y);
			in[y]++;
		}
	}
	toposort();
	if(tot != n)
		cout << "no solution" << "\n";
	else
	{
		cout << n << "\n";
		for(int i = 1; i <= n; i++)
			cout << a[i] << " ";
		cout << "\n";
	}
	return 0;
}

9.强联通分量

(1)Tarjan

#include <bits/stdc++.h>
using namespace std;
#define int long long
int n,m;
int dfn[10010],low[10010],co[10010],col = 0,tot = 0,t[10010],ans = 0,head[10010],cnt = 0;
bool ins[10010];
stack<int> st;

struct Node
{
	int to,nex;
}e[50010];

void add(int x,int y)
{
	cnt++;
	e[cnt].to = y;
	e[cnt].nex = head[x];
	head[x] = cnt;
}

void tarjan(int u)
{
	dfn[u] = low[u] = ++tot;
	st.push(u);
	ins[u] = true;
	for(int i = head[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(ins[v])
			low[u] = min(low[u],low[v]);
	}
	if(low[u] == dfn[u])
	{
		int cnt = 0;
		col++;
		int y;
		while(y = st.top())
		{
			st.pop();
			co[y] = col;
			cnt++;
			ins[y] = false;
			if(u == y)
				break;
		}
		if(cnt > 1)
			ans++;
	}
}

signed main()
{
	cin >> n >> m;
	for(int i = 1; i <= m; i++)
	{
		int a,b;
		cin >> a >> b;
		add(a,b);
	}
	for(int i = 1; i <= n; i++)
	{
		if(!dfn[i])
			tarjan(i);
	}
	cout << ans << "\n";
	return 0;
}

(2)计算割点数量

#include <bits/stdc++.h>
using namespace std;
#define int long long
vector<int> v[110];
int n,tot = 0,low[110],dfn[110],root = 0,ans = 0;

bool tarjan(int x)
{
	dfn[x] = low[x] = ++tot;
	bool flag = false;
	int child = 0;
	for(int i = 0; i < v[x].size(); i++)
	{
		int y = v[x][i];
		if(!dfn[y])
		{
			tarjan(y);
			child++;
			low[x] = min(low[x],low[y]);
			if(dfn[x] <= low[y])
				flag = true;
		}
		else
			low[x] = min(low[x],dfn[y]);
	}
	if(x == root && child < 2)
		flag = false;
	if(flag)
		ans++;
}

signed main()
{
	while(true)
	{
		memset(dfn,0,sizeof(dfn));
		memset(low,0,sizeof(low));
		tot = 0;
		ans = 0;
		root = 0;
		cin >> n;
		for(int i = 1; i <= n; i++)
			v[i].clear();
		if(n == 0)
			break;
		while(true)
		{
			int x;
			cin >> x;
			if(x == 0)
				break;
			string s;
			getline(cin,s);
			s = s + ' ';
			int i = 0,num = 0;
			while(s[i] < '0')
				i++;
			for(; i < s.length(); i++)
			{
				if(s[i] >= '0' && s[i] <= '9')
					num = num * 10 + (s[i] - '0');
				else if(num != 0)
				{
					v[num].push_back(x);
					v[x].push_back(num);
					num = 0;
				}
			}
		}
		for(int i = 1; i <= n; i++)
		{
			if(!dfn[i])
				root = i,tarjan(i);
		}
		cout << ans << "\n";
	}
	return 0;
}

(3)计算桥数量

#include <bits/stdc++.h>
using namespace std;
#define int long long
vector<int> v[30010];
int n,m,tot = 0,ans = 0,low[30010],dfn[30010];

void tarjan(int x,int fa)
{
	dfn[x] = low[x] = ++tot;
	for(int i = 0; i < v[x].size(); i++)
	{
		int y = v[x][i];
		if(y == fa)
			continue;
		if(!dfn[y])
		{
			tarjan(y,x);
			low[x] = min(low[x],low[y]);
			if(dfn[x] < low[y])
				ans++;
		}
		else
			low[x] = min(low[x],dfn[y]);
	}
}

signed main()
{
	while(true)
	{
		memset(low,0,sizeof(low));
		memset(dfn,0,sizeof(dfn));
		tot = 0;
		ans = 0;
		cin >> n >> m;
		for(int i = 1; i <= n; i++)	
			v[i].clear();
		if(n == 0 && m == 0)
			break;
		for(int i = 1; i <= m; i++)
		{
			int a,b;
			cin >> a >> b;
			v[a].push_back(b);
			v[b].push_back(a);
		}
		tarjan(1,0);
		cout << ans << "\n";
	}
	return 0;
}

(4)找割点

#include <bits/stdc++.h>
using namespace std;
#define int long long
bool cut[200010];
int cnt = 0,head[200010],n,a,b,dfn[200010],low[200010],tot;

struct Node
{
    int to,nex;
}e[1000010];

void add(int u,int v)
{
	cnt++;
    e[cnt].to = v;
    e[cnt].nex = head[u];
    head[u] = cnt;
}

void tarjan(int u)
{
    dfn[u] = low[u] = ++tot;
    for(int i = head[u]; i; i = e[i].nex)
    {
        int v = e[i].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u],low[v]);
            if(dfn[u] <= low[v] && u != a && dfn[v] <= dfn[b]) 
                cut[u] = 1;
        }
        else
            low[u] = min(low[u],dfn[v]);
    }
}

signed main()
{
    cin >> n;
    int u,v; 
    while(true)
    {
    	cin >> u >> v;
    	if(u == 0 && v == 0)
    		break;
        add(u,v);
        add(v,u);
    }
    cin >> a >> b;
    tarjan(a);
    for(int i = 1; i <= n; i++)
    {
        if(cut[i])
        {
            cout << i << "\n";
            return 0;
        }
    }
    cout << "No solution" << "\n";
    return 0;
}

10.二叉树

(1)给定后序遍历和中序遍历,求先序遍历

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

void dfs(string zho,string hou)
{
	if(zho.length() > 0)
	{
		char ch = hou[hou.length() - 1];
		cout << ch;
		int k = zho.find(ch);
		dfs(zho.substr(0,k),hou.substr(0,k));
		dfs(zho.substr(k + 1),hou.substr(k,zho.length() - k - 1));
	}
}

signed main()
{
	string a,b;
	cin >> a >> b;
	dfs(a,b);
	cout << "\n";
	return 0;
}

11.素数

(1)费马素性检验

(适用于\(2^{32}\)以内,再大就要错)

mt19937 eng(time(0));
int randint(int a, int b) // 生成a到b之间的随机数
{
    uniform_int_distribution<int> dis(a, b);
    return dis(eng);
}
bool is_prime(int x)
{
    if (x < 3) // 因为生成的a∈[2,x-1],要求x≥3,所以特判1,2
        return x == 2;
    for (int i = 0; i < 12; ++i) // 随机测试12个a
    {
        int a = randint(2, x - 1);
        if (qpow(a, x - 1, x) != 1) // qpow是快速幂
            return false;
    }
    return true;
}

(2)米勒·拉宾素性检验

(适用于\(2^{64}\)以内,再大就要错)

typedef long long ll;
ll qpow(ll a, ll n, ll p) // 快速幂
{
    ll ans = 1;
    while (n)
    {
        if (n & 1)
            ans = (__int128)ans * a % p; // 注意!中间结果可能溢出,需要使用__int128过渡
        a = (__int128)a * a % p;
        n >>= 1;
    }
    return ans;
}
bool is_prime(ll x)
{
    if (x < 3) // 特判1,2
        return x == 2;
    if (x % 2 == 0) // 特判偶数
        return false;
    ll A[] = {2, 325, 9375, 28178, 450775, 9780504, 1795265022}, d = x - 1, r = 0;
    while (d % 2 == 0) // 算出d, r 
        d /= 2, ++r;
    // 或:r = __builtin_ctz(d), d >>= r;
    for (auto a : A)
    {
        ll v = qpow(a, d, x); // a^d
        // 如果a^d≡0,说明是a是x的倍数;如果a^d≡1或-1,说明这串数接下来一定都是1,不用继续计算
        if (v <= 1 || v == x - 1) 
            continue;
        for (int i = 0; i < r; ++i)
        {
            v = (__int128)v * v % x; // 同样使用__int128过渡
            if (v == x - 1 && i != r - 1) // 得到-1,说明接下来都是1,可以退出了
            {
                v = 1;
                break;
            }
            // 在中途而非开头得到1,却没有经过-1,说明存在其他数字y≠-1满足y^2≡1,则x一定不是奇素数
            if (v == 1)  
                return false;
        }
        if (v != 1) // 查看是不是以1结尾
            return false;
    }
    return true;
}

12.输入输出

(1)快读(正负通用)

template <typename T> void read(T &t)
{
    char c = getchar();
    int f = 1;
    t = 0;
    while(c < '0' || c > '9')
    {
        if(c == '-')
            f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
    {
        t = t * 10 + (c - '0');
        c = getchar();
    }
    t *= f;
}

13.高斯消元

(1)简单模板(P3389【模板】高斯消元法&题解)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
double map[111][111];
double ans[111];
double eps=1e-7;
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n+1;j++)
            scanf("%lf",&map[i][j]);
    for(int i=1;i<=n;i++){
        int r=i;
        for(int j=i+1;j<=n;j++)
            if(fabs(map[r][i])<fabs(map[j][i]))
                r=j;//find_the_biggest_number_of_the_first_column(at present) 
        if(fabs(map[r][i])<eps){
            printf("No Solution");
            return 0;
        }
        if(i!=r)swap(map[i],map[r]);//对换一行或一列,属于找最大当前系数的其中一步。(这样就可以只处理当前行的系数啦!) 
        double div=map[i][i];
        for(int j=i;j<=n+1;j++)
            map[i][j]/=div;
        for(int j=i+1;j<=n;j++){
            div=map[j][i];
            for(int k=i;k<=n+1;k++)
                map[j][k]-=map[i][k]*div;
        }
    }
    ans[n]=map[n][n+1];
    for(int i=n-1;i>=1;i--){
        ans[i]=map[i][n+1];
        for(int j=i+1;j<=n;j++)
            ans[i]-=(map[i][j]*ans[j]);
    }//回带操作
    for(int i=1;i<=n;i++)
        printf("%.2lf\n",ans[i]);
}
posted @ 2023-10-01 15:14  夹着曲奇的main包  阅读(56)  评论(0)    收藏  举报
Title