模板库

No_wonderの模板们

更多模板

蒟蒻就学了一点点东西,距离建立一个成熟的模板库还是很远na,加油!!!

其他类

模拟退火

真正的人品无惧于参数的调控。

int SA()//模拟退火
{
	double t=10000,now=ans,xz=0.97;
	while(t>0.0001)
	{
		int x=rand()%n+1,y=rand()%n+1;//随机匹配
		swap(A[x],A[y]);			  //随机到另一个状态 
		double res=calc();			  //算出此时的解	
		if(res<now ||exp(-ch)/t>(double)(rand()%100/100.00))
			now=res;				  //更改最优解 
		else
			swap(A[x],A[y]);		  //不转移解的话就把状态换回来 
		t*=xs;
	}
}

归并排序

洛谷P1177

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN=1e5+5;							//100005 
int a[MAXN], temp[MAXN], n;

void MergeSort(int l, int r)					//再次提醒函数慎用inline,不清楚能不能用就不要用 
{
	int mid=(l+r)>>1; 
    if(l==r)	return;
    MergeSort(l, mid);
	MergeSort(mid+1, r);
    int i=l, j=mid+1, k=l;						//开始2路归并 
    while(i<=mid && j<=r)
    {
        if(a[i]<=a[j])		temp[k++]=a[i++];
        else				temp[k++]=a[j++];
    }
    while(i<=mid)			temp[k++]=a[i++];
    while(j<=r)				temp[k++]=a[j++];
    for(int i=l; i<=r; i++)	a[i]=temp[i];
    return;
}

int main(void)
{
    scanf("%d", &n);
    for(int i=1; i<=n; i++)	scanf("%d", &a[i]);
    MergeSort(1, n);
    for(int i=1; i<=n; i++)	printf("%d ", a[i]);
    return 0;
}

高精度加减乘

#include<bits/stdc++.h>
using namespace std;
void init(int *a,int n)
{
	for(int i=0;i<n;i++)
	a[i]=0;
	char s[200];
	scanf("%s",s);
	a[0]=strlen(s);
	for(int i=1;i<=a[0];i++)
	a[i]=s[a[0]-i]-'0';
	return ;
}
void print(int *a)
{
	for(int i=a[0];i>=1;i--)
	printf("%d",a[i]);
	printf("\n");
	return ;
}
void sum(int *a,int *b,int *c,int n)
{
	for(int i=0;i<n;i++)
	c[i]=0;
	int i=1;
	int jw=0;
	while(i<=a[0]||i<=b[0])
		{
		c[i]=a[i]+b[i]+jw;
		jw=c[i]/10;
		c[i]=c[i]%10;
		i++;
		}
		c[i]=jw;
		if(c[i])c[0]=i;
		else c[0]=i-1;	
} 
int cmp(int *a,int *b)
{
	if(a[0]>b[0])return 1;
	else if(a[0]<b[0])return 0;
	else 
	{
		for(int i=a[0];i>=1;i--)
		{
		if(a[i]<b[i])return 0;
		if(a[i]>b[i])return 1;	
		}
	}
	return 1;
}
void sub(int *a,int *b,int *c,int n)
{
		for(int i=0;i<n;i++)
		c[i]=0;
	
		int i=1;
		if(cmp(a,b))
		{
		while(i<=a[0]||i<=b[0])
		{
			c[i]=a[i]-b[i];
			if(c[i]<0)
			{
				a[i+1]--;
				c[i]+=10;
			}
			i++;
		}
		while(c[i]==0&&i>1)i--;
		c[0]=i;
		}
		else
		{
			printf("-");
		while(i<=a[0]||i<=b[0])
		{
			c[i]=b[i]-a[i];
			if(c[i]<0)
			{
				b[i+1]--;
				c[i]+=10;
			}
			i++;
		}
		while(c[i]==0&&i>1)i--;
		c[0]=i;
		return ;
		}
		
	}
void jh(int *a,int *b)
{
	for(int i=0;i<200;i++)
	a[i]=0;
	for(int i=b[0];i>=0;i--)
	a[i]=b[i];
}

void mul(int *a,int *b,int *c,int n)
{
	for(int i=0;i<200;i++)
	c[i]=0;
	for(int i=1;i<=a[0];i++)
	{
		int jw=0;
		for(int j=1;j<=b[0];j++)
		{
		c[i+j-1]+=a[i]*b[i]+jw;
		jw=c[i+j-1]/10;
		c[i+j-1]%=10;
		}
	c[i+b[0]]=jw;
	i++;	
	}
	c[0]=a[0]+b[0];
	while(!c[c[0]]&&c[0]>1)c[0]--;
	return ;
	
}
int main()
{
	int a[2000],b[2000],c[2000];
	init(a,2000);
	init(b,2000);
	//print(a);
	//print(b);
	//sum(a,b,c,2000);
	//print(c);
	sub(a,b,c,2000);
	print(c);
	//mul(a,b,c,2000);
	//print(c);
	//mulx(a,3);
	///print(a);
	return 0;
}

不怕死就用的八聚氧

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(3,"Ofast","inline")
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
%:pragma GCC optimize("-fgcse")
%:pragma GCC optimize("-fgcse-lm")
%:pragma GCC optimize("-fipa-sra")
%:pragma GCC optimize("-ftree-pre")
%:pragma GCC optimize("-ftree-vrp")
%:pragma GCC optimize("-fpeephole2")
%:pragma GCC optimize("-ffast-math")
%:pragma GCC optimize("-fsched-spec")
%:pragma GCC optimize("unroll-loops")
%:pragma GCC optimize("-falign-jumps")
%:pragma GCC optimize("-falign-loops")
%:pragma GCC optimize("-falign-labels")
%:pragma GCC optimize("-fdevirtualize")
%:pragma GCC optimize("-fcaller-saves")
%:pragma GCC optimize("-fcrossjumping")
%:pragma GCC optimize("-fthread-jumps")
%:pragma GCC optimize("-funroll-loops")
%:pragma GCC optimize("-fwhole-program")
%:pragma GCC optimize("-freorder-blocks")
%:pragma GCC optimize("-fschedule-insns")
%:pragma GCC optimize("inline-functions")
%:pragma GCC optimize("-ftree-tail-merge")
%:pragma GCC optimize("-fschedule-insns2")
%:pragma GCC optimize("-fstrict-aliasing")
%:pragma GCC optimize("-fstrict-overflow")
%:pragma GCC optimize("-falign-functions")
%:pragma GCC optimize("-fcse-skip-blocks")
%:pragma GCC optimize("-fcse-follow-jumps")
%:pragma GCC optimize("-fsched-interblock")
%:pragma GCC optimize("-fpartial-inlining")
%:pragma GCC optimize("no-stack-protector")
%:pragma GCC optimize("-freorder-functions")
%:pragma GCC optimize("-findirect-inlining")
%:pragma GCC optimize("-fhoist-adjacent-loads")
%:pragma GCC optimize("-frerun-cse-after-loop")
%:pragma GCC optimize("inline-small-functions")
%:pragma GCC optimize("-finline-small-functions")
%:pragma GCC optimize("-ftree-switch-conversion")
%:pragma GCC optimize("-foptimize-sibling-calls")
%:pragma GCC optimize("-fexpensive-optimizations")
%:pragma GCC optimize("-funsafe-loop-optimizations")
%:pragma GCC optimize("inline-functions-called-once")
%:pragma GCC optimize("-fdelete-null-pointer-checks")

图论

最短路

dijkstra堆优化

洛谷P1339
我会线段树!我会斐波那契堆!!!
我会堆

#include<bits/stdc++.h>
#include<queue>
#define inf INT_MAX/2-1                          
using namespace std;
struct Edge{
    int to,next,dis;
}e[100000];
struct dist{
    int num,dis;
    dist(int n,int d)
    {
        num=n;
        dis=d;
    }
    bool operator < (const dist r)const
    {
        return dis>r.dis;
    }
};
int n,m,c1,c2,num;
int head[100010],dis[100010],vis[100010];
void add(int from,int to,int dis)
{
    e[++num].to=to;
    e[num].next=head[from];
    e[num].dis=dis;
    head[from]=num;
}
void dijkstra(int now)
{
    dis[now]=0;
    priority_queue <dist> q;
    q.push(dist(now,dis[now]));
    while(!q.empty())
    {
        int u=q.top().num;
        int v=q.top().dis;
        q.pop();
        if(vis[u])continue;
        else
        {
            vis[u]=1;
            for(int i=head[u];i;i=e[i].next)
            {
                int to=e[i].to;
                if(v+e[i].dis<dis[to])
                {
                    dis[to]=v+e[i].dis;
                    q.push(dist(to,dis[to]));
                }
            }
        }   
    }
}
int main()
{
    cin>>n>>m>>c1>>c2;
    for(int i=1;i<=m;i++)
    {
        int x,y,dis;
        cin>>x>>y>>dis;
        add(x,y,dis);
        add(y,x,dis);
    }
    for(int i=0;i<=n;i++)
	dis[i]=inf; 
    dijkstra(c1);
    cout<<dis[c2];
}

SPFA

洛谷P1339
未优化,谁用谁知道

#include<bits/stdc++.h>
#include<queue>
#define inf 1000000
using namespace std; 
int n,m,head[100010],cnt,c1,c2,dis[100010],vis[100010];
queue<int> q;
struct Edge{
	int to;
	int next;
	int dist;
}e[100010];
void add(int from,int to,int dist)
{
	e[++cnt].next=head[from];
	e[cnt].to=to;
	e[cnt].dist=dist;
	head[from]=cnt;
}
void spfa(int now)
{
	dis[now]=0;
	vis[now]=1;
	q.push(now);
	while(!q.empty())
	{
		int t=q.front();
		q.pop();
		vis[t]=0;
		for(int i=head[t];i;i=e[i].next)
		{
			if(dis[e[i].to]>dis[t]+e[i].dist)
			{
				dis[e[i].to]=dis[t]+e[i].dist;
				if(!vis[e[i].to])
				{
					vis[e[i].to]=1;
					q.push(e[i].to);
				}
			}
		}
	}
}
int main()
{
	scanf("%d%d%d%d",&n,&m,&c1,&c2);
	for(int i=1;i<=m;i++)
	{
		int x,y,dist;
		scanf("%d%d%d",&x,&y,&dist);
		add(x,y,dist);
		add(y,x,dist);
	}
	memset(dis,inf,sizeof(dis));
	spfa(c1);
	printf("%d",dis[c2]);
	return 0;
}

SPFA SLF+LLL

SPFA优化后的船新版本,老韩再也不怕我被卡7个点了!

//SPFA+SLF+LLL
#include<iostream>
#include<cstdio>
#include<cstring>
#include<deque>
using namespace std;
const int maxn=1e4+5, maxm=5e5+5, INF=2147483647;
int dis[maxn], v[maxn], n, m, s;
struct edge{
	int t, w; edge *nxt;
	edge(int to, int len, edge *next){ t=to, w=len, nxt=next; }
};
edge *h[maxn];
void add(int x, int y, int z){ h[x]=new edge(y, z, h[x]); }

void SPFA(int s)
{
	int cnt=0, sum=0;														//cnt为队列中元素个数,sum为队列中dis值总和 
    for(int i=1; i<=n; i++)   dis[i]=(i==s) ? 0 : INF;
    deque<int> Q;															//Q为双端队列 
    Q.push_back(s), v[s]=1, cnt=1;
    while(!Q.empty())
    {
        int x=Q.front();
		while(cnt*dis[x]>sum)												//取出来,放后去,直到找到一个比平均值小的点 
		{
			Q.pop_front();
			Q.push_back(x);
			x=Q.front();
		}
		Q.pop_front();
		cnt--, sum-=dis[x], v[x]=false;										//出队后,更新队列大小及队列dis值之和  
		for(edge *p=h[x]; p; p=p->nxt)
            if(dis[p->t]>dis[x]+p->w)
            {
                dis[p->t]=dis[x]+p->w;
                if(!v[p->t])
                {
                    v[p->t]=1;
                    if(Q.empty() || dis[p->t]>dis[Q.front()])	Q.push_back(p->t);
                    else										Q.push_front(p->t);
                    cnt++, sum+=dis[p->t]; 									//入队后,更新队列大小及队列dis值之和 
                }
            }
    }
}

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

01最短路

具体实现是用双端队列,0排在队头,1排在队尾,这样搜索的时候就会优先走0路

Luogu P1948

#pragma GCC optimize(3)
#include<bits/stdc++.h>
#include<queue>
using namespace std;
int n,p,k,maxn;
int head[10010],cnt;
int d[10010],vis[10010];
struct Edge{
	int to;
	int next;
	int dis;
}e[20020];
void add_edge(int from,int to,int dis)
{
	e[++cnt].to=to;
	e[cnt].next=head[from];
	e[cnt].dis=dis;
	head[from]=cnt;
}
bool check(int x)
{
	memset(d,0,sizeof d);
	memset(vis,0,sizeof vis);
	deque <int> q;
	q.push_back(1);
	d[1]=0;
	vis[1]=1;
	while(!q.empty())
	{
		int a=q.front();
		q.pop_front();
		for(register int i=head[a];i;i=e[i].next)
		{
			int y=e[i].to;
			if(!vis[y] || d[y]>=d[a]+1)
			if(e[i].dis<=x)
			{
				vis[y]=1;
				q.push_front(y);
				d[y]=d[a];
			}
			else
			{
				vis[y]=1;
				q.push_back(y);
				d[y]=d[a]+1;
			}
		}
	}
	if(d[n]>k)
	return 0;
	return 1;
}
int main()
{
	scanf("%d%d%d",&n,&p,&k);
	for(register int i=1;i<=p;i++)
	{	
	int ai,bi,li;
	scanf("%d%d%d",&ai,&bi,&li);
	add_edge(ai,bi,li);
	add_edge(bi,ai,li);
	maxn=max(maxn,li);
	}
	int l=1,r=maxn;
	while(l<r)
	{
		int mid=(l+r)>>1;
		if(check(mid))
		r=mid;
		else
		l=mid+1;
	}
	if(l!=1)
	printf("%d",l);
	else
	printf("-1");
}

最小生成树

Pirm

洛谷P3366

#include<bits/stdc++.h>
#include<queue>
#define inf INT_MAX/4
using namespace std;
int n,m,cnt,ans,sum,now,dis[1000010],head[1000010],vis[1000010];
struct Edge{
	int next;
	int to;
	int dist;
}e[1000010];
struct dist;
struct dist{
	int num;
	int dis;
	dist(int pn,int pw)
	{
		num=pn;
		dis=pw;
	}
	bool operator <(const dist &r)const
	{
		return dis>r.dis;
	} 
};
void add(int from,int to,int dist)
{
	e[++cnt].next=head[from];
	e[cnt].to=to;
	e[cnt].dist=dist;
	head[from]=cnt; 
}
void Pirm()
{
	for(int i=2;i<=n;i++)
	dis[i]=inf;
	priority_queue <dist> q;
	q.push(dist(1,dis[1]));
	while(!q.empty()&&sum<n)
	{
		int f1=q.top().dis,f2=q.top().num;
		q.pop();
		if(vis[f2])continue;
		sum++;
		ans+=f1;
		vis[f2]=1;
		for(int i=head[f2];i;i=e[i].next)
		if(e[i].dist<dis[e[i].to])
		{
		dis[e[i].to]=e[i].dist;
		q.push(dist(e[i].to,dis[e[i].to]));	
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=2;i<=n;i++)
	dis[i]=inf;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		add(u,v,w);
		add(v,u,w);
	}
	Pirm();
	printf("%d",ans);
}

Kruskal

#include<bits/stdc++.h>
using namespace std;
int n,m,fa[100010],cnt,sum,ans;
struct Edge
{
	int from;
	int to;
	int dist;	
	bool operator < (const Edge r)const
	{
		return dist<r.dist;			
		//如果要求最大生成树把这里的'<'改成'>'就可以了!
	} 
}a[1000010];
int find(int x)
{
	if(x==fa[x])return x;
	return fa[x]=find(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++)
	{
		int u,v,w;
		scanf("%d%d%d",&u,&v,&w);
		a[++cnt]=(Edge){u,v,w};
	}
	sort(a+1,a+cnt+1);
	for(int i=1;i<=cnt;i++)
	{
		if(find(a[i].from)!=find(a[i].to))
		{
			sum++;
			int f1=find(a[i].from),f2=find(a[i].to);
			fa[f2]=f1;
			ans+=a[i].dist;
			if(sum==n-1)
			{
				printf("%d",ans);
				return 0;
			}
		}	
	}	
	printf("orz");
}

拓扑排序

本校OJ P233

#include<bits/stdc++.h>
#include<queue>
using namespace std;
int n,m,cnt,ans,head[1000010],rd[1000010],flag,money[1000010];
struct Edge{
	int to;
	int next;
}e[1000010];
queue <int> q;
void add(int from,int to)
{
	e[++cnt].next=head[from];
	e[cnt].to=to;
	head[from]=cnt;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	money[i]=100;
	for(int i=1;i<=m;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		add(v,u);
		rd[u]++;
	}
	for(int i=1;i<=n;i++)
		if(!rd[i])
			q.push(i);
			int num=0;
	while(!q.empty())
		{
			num++;
			int now=q.front();
			q.pop();
			for(int i=head[now];i;i=e[i].next)
			{
				rd[e[i].to]--;
				if(!rd[e[i].to])
				q.push(e[i].to);
				money[e[i].to]=max(money[now]+1,money[e[i].to]);
			}
		}
			if(num==n)
			flag=1;
	if(!flag)
	printf("Poor Xed");
	else
	{
		for(int i=1;i<=n;i++)
		ans+=money[i];
		printf("%d",ans);
	}
}

Tarjan之SCC+缩点

洛谷P2002

#include<bits/stdc++.h>
#include<stack>
using namespace std;
int num,head[100010],dfn[100010],low[100010],cnt,vis[100010];
int sum[100010],bj[100010],tot,qwq[100010];
struct Edge{
    int to,next;
}edge[500010];
inline void add(int from,int to){
    num++;
    edge[num].to=to;
    edge[num].next=head[from];
    head[from]=num;
}
stack<int>s;    
inline void tarjan(int x){
    cnt++;
    dfn[x]=low[x]=cnt;
    s.push(x);
    vis[x]=1;
    for(register int i=head[x];i;i=edge[i].next){
        int y=edge[i].to;
        if(dfn[y]==0){  
            tarjan(y);  
            low[x]=min(low[x],low[y]);
        }
        else if(vis[y]==1){
            low[x]=min(low[x],dfn[y]);
        }
    }
    if(low[x]==dfn[x]){
        int z;
        tot++;  
        while(s.top()!=x){  
            sum[tot]++; 
            z=s.top(); 
            vis[z]=0;   
            bj[z]=tot;  
            s.pop();    
        }
        sum[tot]++;
        z=s.top();
        vis[z]=0;
        bj[z]=tot;
        s.pop();
    }
    return;
}
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    int x,y;
    for(register int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        add(x,y);
    }
    for(register int i=1;i<=n;i++){
        if(dfn[i]==0)
            tarjan(i);
    }
    for(register int i=1;i<=n;i++){     
        for(register int j=head[i];j;j=edge[j].next){
            int y=edge[j].to;   
            if(bj[i]!=bj[y]){
                qwq[bj[y]]=1;
            }
        }
    }
    int ans=0;
    for(register int i=1;i<=tot;i++){
        if(qwq[i]==0){
            ans++;
        }
    }
    printf("%d",ans);
    return 0;
}

LCA

倍增法

洛谷P3379

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
const int N=6e5;
int n,m,s,t,tot=0,f[N][20],d[N],ver[2*N],Next[2*N],head[N];
queue<int> q;
void add(int x,int y)
{
    ver[++tot]=y,Next[tot]=head[x],head[x]=tot;
}//邻接表存边操作。由于只求LCA时不关心边权,因此可以不存边权
void bfs()
{
    q.push(s);
    d[s]=1;//将根节点入队并标记
    while(q.size())
    {
        int x=q.front();q.pop();//取出队头
        for(int i=head[x];i;i=Next[i])
        {
            int y=ver[i];
            if(d[y])
                continue;
            d[y]=d[x]+1;
            f[y][0]=x;//初始化,因为y的父亲节点就是x
            for(int j=1;j<=t;j++)
                f[y][j]=f[f[y][j-1]][j-1];//递推f数组
            q.push(y);
        }
    }
}
int lca(int x,int y)
{
    if(d[x]>d[y])
        swap(x,y);
    for(int i=t;i>=0;i--)
        if(d[f[y][i]]>=d[x])
            y=f[y][i];//尝试上移y
    if(x==y)
        return x;//若相同说明找到了LCA
    for(int i=t;i>=0;i--)
        if(f[x][i]!=f[y][i])
        {
            x=f[x][i],y=f[y][i];
        }//尝试上移x、y并保持它们不相遇
    return f[x][0];//当前节点的父节点即为LCA
}
int main()
{
    cin>>n>>m>>s;
    t=log2(n)+1;
    for(int i=1;i<n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add(x,y),add(y,x);
    }
    bfs();
    while(m--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        printf("%d\n",lca(a,b));
    }
    return 0;
}

Tarjan(离线算法)

洛谷P3379

#include<bits/stdc++.h>
using namespace std;
int n,k,q,v[100000];
map<pair<int,int>,int> ans;//存答案
int t[100000][10],top[100000];//存储查询关系
struct node{
    int l,r;
};
node s[100000];
/*并查集*/
int fa[100000];
void reset(){
    for (int i=1;i<=n;i++){
        fa[i]=i;
    }
}
int getfa(int x){
    return fa[x]==x?x:getfa(fa[x]);
}
void marge(int x,int y){
    fa[getfa(y)]=getfa(x);
}
/*------*/
void tarjan(int x){
    v[x]=1;//标记已访问
    node p=s[x];//获取当前结点结构体
    if (p.l!=-1){
        tarjan(p.l);
        marge(x,p.l);
    }
    if (p.r!=-1){
        tarjan(p.r);
        marge(x,p.r);
    }//分别对l和r结点进行操作
    for (int i=1;i<=top[x];i++){
        if (v[t[x][i]]){
            cout<<getfa(t[x][i])<<endl;
        }//输出
    }
}
int main(){
    cin>>n>>q;
    for (int i=1;i<=n;i++){
        cin>>s[i].l>>s[i].r;
    }
    for (int i=1;i<=q;i++){
        int a,b;
        cin>>a>>b;
            t[a][++top[a]]=b;//存储查询关系
            t[b][++top[b]]=a;
    }
    reset();//初始化并查集
    tarjan(1);//tarjan 求 LCA
}

树链剖分

#include <cstdio>
#include <cstdlib>
#define maxm 200010
struct edge{int to,len,next;}E[maxm];
int cnt,last[maxm],fa[maxm],top[maxm],deep[maxm],siz[maxm],son[maxm],val[maxm];
void addedge(int a,int b,int len=0)
{
    E[++cnt]=(edge){b,len,last[a]},last[a]=cnt;
}
void dfs1(int x)
{
    deep[x]=deep[fa[x]]+1;siz[x]=1;
    for(int i=last[x];i;i=E[i].next)
    {
        int to=E[i].to;
        if(fa[x]!=to&&!fa[to]){
            val[to]=E[i].len;
            fa[to]=x;
            dfs1(to);
            siz[x]+=siz[to];
            if(siz[son[x]]<siz[to])son[x]=to;
        }
    }
}
void dfs2(int x)
{
    if(x==son[fa[x]])top[x]=top[fa[x]];
    else top[x]=x;
    for(int i=last[x];i;i=E[i].next)if(fa[E[i].to]==x)dfs2(E[i].to);
}
void init(int root){dfs1(root),dfs2(root);}
int query(int x,int y)
{
    for(;top[x]!=top[y];deep[top[x]]>deep[top[y]]?x=fa[top[x]]:y=fa[top[y]]);
    return deep[x]<deep[y]?x:y;
}
int n,m,x,y,v;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++)
    {
        scanf("%d%d",&x,&y);addedge(x,y,v);addedge(y,x,v);
    }
    init(1);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        printf("%d\n",query(x,y));
    }
    return 0 ;
}

数据结构

线段树

区间加减带区间和

代码五分钟,bug两小时
洛谷P3372

#include<bits/stdc++.h>
#define ri register int 
#define ls(k) (k)<<1
#define rs(k) (k)<<1|1
using namespace std;
int n,m,a[100010];
struct llk{
	long long l,r,lazy,sum;
}tree[500010];
int read()
{
	int w=1,s=0;
	char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
	return s*w;
}
void build(int i,int l,int r)
{
	tree[i].l=l;
	tree[i].r=r;
	if(l==r)
	{
		tree[i].sum=a[l];
		return ;
	}
	int mid=(l+r)>>1;
	build(ls(i),l,mid);
	build(rs(i),mid+1,r);
	tree[i].sum=tree[ls(i)].sum+tree[rs(i)].sum;
}
void down(int i)
{
	tree[ls(i)].lazy+=tree[i].lazy;
	tree[ls(i)].sum+=(tree[ls(i)].r-tree[ls(i)].l+1)*tree[i].lazy;
	tree[rs(i)].lazy+=tree[i].lazy;
	tree[rs(i)].sum+=(tree[rs(i)].r-tree[rs(i)].l+1)*tree[i].lazy;
	tree[i].lazy=0;
}
void update(int i,int l,int r,int k)
{
	if(tree[i].l>r || tree[i].r<l)return ;
	if(tree[i].l>=l && tree[i].r<=r)
	{
		tree[i].lazy+=k;
		tree[i].sum+=(tree[i].r-tree[i].l+1)*k;
		return ;
	}
	if(tree[i].lazy>0)down(i);
	update(ls(i),l,r,k);
	update(rs(i),l,r,k);
	tree[i].sum=tree[ls(i)].sum+tree[rs(i)].sum;
}
long long query(int i,int l,int r)
{
	if(tree[i].l>r || tree[i].r<l)return 0;
	if(tree[i].l>=l&&tree[i].r<=r)return tree[i].sum;
	if(tree[i].lazy>0)down(i);
	return query(ls(i),l,r)+query(rs(i),l,r);
}
int main()
{
	n=read();
	m=read();
	for(ri i=1;i<=n;i++)
	a[i]=read();
	build(1,1,n);
	for(ri i=1;i<=m;i++)
	{
		int t,x,y;
		t=read();
		if(t==1)
		{
			int k;
			x=read();
			y=read();
			k=read();
			update(1,x,y,k);
		}
		else
		{
			x=read();
			y=read();
			printf("%lld\n",query(1,x,y));
		}
	}
} 

乘+加

洛谷P3373
代码五十分钟,bug二十小时

#include<bits/stdc++.h>
#define ri register int
#define ls(k) (k)<<1//宏定义最外头要打上括号,这是良好的编程习惯 ((k)<<1)
#define rs(k) (k)<<1|1
using namespace std;
int n,m,p;
long long a[500050];
struct node{
    long long sum,mul,add;
}tree[500050];
int read()
{
    int w=1,s=0;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
    return s*w;
}
void build(int i,int l,int r)
{
    tree[i].mul=1;
    tree[i].add=0;
    if(l==r)
    tree[i].sum=a[l];
    else
    {
        int mid=(l+r)>>1;
        build(ls(i),l,mid);
        build(rs(i),mid+1,r);
        tree[i].sum=tree[ls(i)].sum+tree[rs(i)].sum;
    }
    tree[i].sum%=p;
    return;
}
void pushdown(int i,int l,int r)
{
    int mid=(l+r)>>1;
    tree[ls(i)].sum=(tree[ls(i)].sum*tree[i].mul+tree[i].add*(mid-l+1))%p;
    tree[rs(i)].sum=(tree[rs(i)].sum*tree[i].mul+tree[i].add*(r-mid))%p;
    tree[ls(i)].mul=(tree[ls(i)].mul*tree[i].mul)%p;
    tree[rs(i)].mul=(tree[rs(i)].mul*tree[i].mul)%p;
    tree[ls(i)].add=(tree[ls(i)].add*tree[i].mul+tree[i].add)%p;
    tree[rs(i)].add=(tree[rs(i)].add*tree[i].mul+tree[i].add)%p;
    tree[i].mul=1;
    tree[i].add=0;
    return ;
}
void mul(int i,int stdl,int stdr,int l,int r,long long k)
{
    if(r<stdl||stdr<l) return ;
    if(l<=stdl&&r>=stdr)
    {
        tree[i].sum=(tree[i].sum*k)%p;
        tree[i].mul=(tree[i].mul*k)%p;
        tree[i].add=(tree[i].add*k)%p;
        return ;
    }
    pushdown(i,stdl,stdr);
    int mid=(stdl+stdr)>>1;
    mul(ls(i),stdl,mid,l,r,k);
    mul(rs(i),mid+1,stdr,l,r,k);
    tree[i].sum=(tree[ls(i)].sum+tree[rs(i)].sum)%p;
    return;
}
void add(int i,int stdl,int stdr,int l,int r,long long k)
{
    if(r<stdl || l>stdr)return ;
    if(r>=stdr&&l<=stdl)
    {
        tree[i].add=(tree[i].add+k)%p;
        tree[i].sum=(tree[i].sum+k*(stdr-stdl+1))%p;
        return ;
    }
    pushdown(i,stdl,stdr);
    int mid=(stdl+stdr)>>1;
    add(ls(i),stdl,mid,l,r,k);
    add(rs(i),mid+1,stdr,l,r,k);
    tree[i].sum=(tree[ls(i)].sum+tree[rs(i)].sum)%p;
    return ;
}
long long query(int i,int stdl,int stdr,int l,int r)
{
    if(r<stdl||l>stdr)return 0;
    if(r>=stdr&&l<=stdl) return tree[i].sum;
    pushdown(i,stdl,stdr);
    int mid=(stdl+stdr)>>1;
    return (query(ls(i),stdl,mid,l,r)+query(rs(i),mid+1,stdr,l,r))%p;
}
int main()
{
    n=read();m=read();p=read();
    for(ri i=1;i<=n;i++)
    scanf("%lld",&a[i]);
    build(1,1,n);
    for(ri i=1;i<=m;i++)
    {
        int t;
        t=read();
        int x,y;
        long long k;
        if(t==1)
        {
            x=read();
            y=read();
            scanf("%lld",&k);
            mul(1,1,n,x,y,k);
        }
        else if(t==2)
        {
            x=read();
            y=read();
            scanf("%lld",&k);
            add(1,1,n,x,y,k);
        }
        else
        {
            x=read();
            y=read();
            printf("%lld\n",query(1,1,n,x,y));
        }
    }
    return 0;
}


打线段树手残了问了学长,于是有了下面这段话QAQ

调试程序的一大秘诀是打印中间值
有闲心的话去学一下gdb,虽然我没用过,但是上了大学用idea debug的时候能单步调试非常地爽(
没闲心就像我一样printf打印中间值
这次debug,第一个m是肉眼看出来的。第二个是打印中间值看出来的。打印每步过后整棵线段树的sum,add,mul, 没看出来什么问题就把每次进入query函数的参数打印出来,手动执行,然后就发现不对力
打印中间值就相当于不会用gdb的人手动模拟了一个gdb观察中间变量,永远滴神(

求区间最值

#include <stdio.h>
#include <string.h>
 
#define maxn 1000002
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
 
int T[maxn << 2];
 
int min(int a, int b) {
        return a < b ? a : b;
}
 
void pushUp(int rt) {
        T[rt] = min(T[rt<<1], T[rt<<1|1]);
}
 
void build(int l, int r, int rt) {
        if(l == r) {
                scanf("%d", &T[rt]);
                return;
        }
        int mid = (l + r) >> 1;
        build(lson);
        build(rson);
        pushUp(rt);
}
 
void update(int pos, int V, int l, int r, int rt) {
        if(l == r) {
                T[rt] = V;
                return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid) update(pos, V, lson);
        else update(pos, V, rson);
        pushUp(rt);
}
 
int query(int L, int R, int l, int r, int rt) {
        if(L == l && R == r) return T[rt];
        int mid = (l + r) >> 1;
        if(R <= mid) return query(L, R, lson);
        else if(L > mid) return query(L, R, rson);
        return min(query(L, mid, lson), query(mid + 1, R, rson));
}
 
int main() {
        int N, i, Q, a, c, b;
        scanf("%d", &N);
        build(1, N, 1);
        scanf("%d", &Q);
        while(Q--) {
                scanf("%d%d%d", &c, &a, &b);
                if(c) update(a, b, 1, N, 1);
                else printf("%d\n", query(a, b, 1, N, 1));
        }
        return 0;
}


树状数组

单点修改+区间查询

#include<bits/stdc++.h>
#define ri register int
using namespace std;
int n,m;
int tree[10001000];
int lowbit(int x)
{
	return x&(-x);
}
void update(int pos,int x)
{
	while(pos<=n)
	{
		tree[pos]+=x;
		pos+=lowbit(pos);
	}
}
int query(int pos)
{
	int ans=0;
	while(pos)
	{
		ans+=tree[pos];
		pos-=lowbit(pos);
	}
	return ans;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(ri i=1;i<=n;i++)
	{
		int x;
		scanf("%d",&x);
		update(i,x);
	}
	for(ri i=1;i<=m;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		if(x==1)	update(y,z);
		else printf("%d\n",query(z)-query(y-1));
	}
}

区间修改+单点查询

#include<bits/stdc++.h>
#define ri register int
using namespace std;
int n,m;
long long tree[500050];
long long lowbit(int x)
{
	return x&(-x);
}
void update(int pos,long long x)
{
	while(pos<=n)
	{
		tree[pos]+=x;
		pos+=lowbit(pos);
	}
}
long long query(int pos)		//单点询问 
{
	long long ans=0;
	while(pos)
	{
		ans+=tree[pos];
		pos-=lowbit(pos);
	}
	return ans;
}
int main()
{
	scanf("%d%d",&n,&m);
	long long last=0;			//差分值初始化 
	for(ri i=1;i<=n;i++)
	{
		long long x;
		scanf("%lld",&x);
		update(i,x-last);
		last=x;
	}
	while(m--)
	{
		int x;
		scanf("%d",&x);
		if(x==1)				//区间修改 
		{
			int l,r,k;
			scanf("%d%d%d",&l,&r,&k);
			update(l,k);
			update(r+1,-k);
		}
		else
		{
			int y;
			scanf("%d",&y);
			printf("%lld\n",query(y));
		}
	}
}

区间修改+区间查询

#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[50005] = {0};
int sum1[50005];    //(D[1] + D[2] + ... + D[n])
int sum2[50005];    //(1*D[1] + 2*D[2] + ... + n*D[n])
int lowbit(int x)
{
    return x&(-x);
}
void updata(int i,int k)
{
    int x=i;
    while(i <= n)
	{
        sum1[i]+=k;
        sum2[i]+=k*(x-1);
        i+=lowbit(i);
    }
}
int getsum(int i)
{        //求前缀和
    int res=0, x=i;
    while(i>0)
	{
        res+=x*sum1[i]-sum2[i];
        i-=lowbit(i);
    }
    return res;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++)
	{
        cin>>a[i];
        updata(i,a[i]-a[i-1]);
    }
    int x,y,k;
    cin>>x>>y>>k;
    updata(x,k);
    updata(y+1,-k);
    int sum = getsum(y) - getsum(x-1);
    return 0;
}

ST表

#include <iostream>
#include <algorithm>

using namespace std;

int a[1010];//原始输入数组
int st[1010][20];//st表

void init(int n)
{
    for (int i = 0; i < n; i++)
        st[i][0] = a[i];

    for (int i = 1; (1 << i) <= n; i++)
    {
        for (int j = 0; j + (1 << i) - 1 < n; j++)
            st[j][i] = min(st[j][i - 1],st[j + (1 << (i - 1))][i - 1]);
    }
}

int search(int l, int r)
{
    int k = (int)(log((double)(r - l + 1)) / log(2.0));
    return min(st[l][k],st[r - (1 << k) + 1][k]);
}

int main()
{
    int n,m;
    while (cin >> n >> m)
    {
        for (int i = 0; i < n; i++)
            cin >> a[i];

        init(n);

        while (m--)
        {
            int l, r;
            cin >> l >> r;
            cout << search(l,r) << endl;;
        }
    }
    return 0;
}

树链剖分+线段树维护

众所周知,树链剖分最难的是模板题
洛谷P3384

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#define Rint register int
#define mem(a,b) memset(a,(b),sizeof(a))
#define Temp template<typename T>
using namespace std;
typedef long long LL;
Temp inline void read(T &x){
    x=0;T w=1,ch=getchar();
    while(!isdigit(ch)&&ch!='-')ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
    x=x*w;
}

#define mid ((l+r)>>1)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define len (r-l+1)

const int maxn=200000+10;
int n,m,r,mod;
int e,beg[maxn],nex[maxn],to[maxn],w[maxn],wt[maxn]; 
int a[maxn<<2],laz[maxn<<2];
int son[maxn],id[maxn],fa[maxn],cnt,dep[maxn],siz[maxn],top[maxn]; 
int res=0;
inline void add(int x,int y){
    to[++e]=y;
    nex[e]=beg[x];
    beg[x]=e;
}
inline void pushdown(int rt,int lenn){
    laz[rt<<1]+=laz[rt];
    laz[rt<<1|1]+=laz[rt];
    a[rt<<1]+=laz[rt]*(lenn-(lenn>>1));
    a[rt<<1|1]+=laz[rt]*(lenn>>1);
    a[rt<<1]%=mod;
    a[rt<<1|1]%=mod;
    laz[rt]=0;
}

inline void build(int rt,int l,int r){
    if(l==r){
        a[rt]=wt[l];
        if(a[rt]>mod)a[rt]%=mod;
        return;
    }
    build(lson);
    build(rson);
    a[rt]=(a[rt<<1]+a[rt<<1|1])%mod;
}

inline void query(int rt,int l,int r,int L,int R){
    if(L<=l&&r<=R){res+=a[rt];res%=mod;return;}
    else{
        if(laz[rt])pushdown(rt,len);
        if(L<=mid)query(lson,L,R);
        if(R>mid)query(rson,L,R);
    }
}

inline void update(int rt,int l,int r,int L,int R,int k){
    if(L<=l&&r<=R){
        laz[rt]+=k;
        a[rt]+=k*len;
    }
    else{
        if(laz[rt])pushdown(rt,len);
        if(L<=mid)update(lson,L,R,k);
        if(R>mid)update(rson,L,R,k);
        a[rt]=(a[rt<<1]+a[rt<<1|1])%mod;
    }
}
inline int qRange(int x,int y){
    int ans=0;
    while(top[x]!=top[y]){ 
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        res=0;
        query(1,1,n,id[top[x]],id[x]);
        ans+=res;
        ans%=mod;
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    res=0;
    query(1,1,n,id[x],id[y]);
    ans+=res;
    return ans%mod;
}

inline void updRange(int x,int y,int k){
    k%=mod;
    while(top[x]!=top[y]){
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        update(1,1,n,id[top[x]],id[x],k);
        x=fa[top[x]];
    }
    if(dep[x]>dep[y])swap(x,y);
    update(1,1,n,id[x],id[y],k);
}

inline int qSon(int x){
    res=0;
    query(1,1,n,id[x],id[x]+siz[x]-1); 
    return res;
}

inline void updSon(int x,int k){
    update(1,1,n,id[x],id[x]+siz[x]-1,k);
}

inline void dfs1(int x,int f,int deep){
    dep[x]=deep;
    fa[x]=f; 
    siz[x]=1;
    int maxson=-1; 
    for(Rint i=beg[x];i;i=nex[i]){
        int y=to[i];
        if(y==f)continue; 
        dfs1(y,x,deep+1); 
        siz[x]+=siz[y];
        if(siz[y]>maxson)son[x]=y,maxson=siz[y];
    }
}

inline void dfs2(int x,int topf){
    id[x]=++cnt; 
    wt[cnt]=w[x]; 
    top[x]=topf; 
    if(!son[x])return; 
    dfs2(son[x],topf); 
    for(Rint i=beg[x];i;i=nex[i]){
        int y=to[i];
        if(y==fa[x]||y==son[x])continue;
        dfs2(y,y); 
    }
}

int main(){
    read(n);read(m);read(r);read(mod);
    for(Rint i=1;i<=n;i++)read(w[i]);
    for(Rint i=1;i<n;i++){
        int a,b;
        read(a);read(b);
        add(a,b);add(b,a);
    }
    dfs1(r,0,1);
    dfs2(r,r);
    build(1,1,n);
    while(m--){
        int k,x,y,z;
        read(k);
        if(k==1){
            read(x);read(y);read(z);
            updRange(x,y,z);
        }
        else if(k==2){
            read(x);read(y);
            printf("%d\n",qRange(x,y));
        }
        else if(k==3){
            read(x);read(y);
            updSon(x,y);
        }
        else{
            read(x);
            printf("%d\n",qSon(x));
        }
    }
}

DP

背包类

01背包

洛谷P1048

#include<bits/stdc++.h>
using namespace std;
int dp[100010],T,N,w[100010],t[100010];
int main()
{
	cin>>T>>N;
	for(int i=1;i<=N;i++)
	cin>>t[i]>>w[i];
	for(int i=1;i<=N;i++)
	for(int j=T;j>=t[i];j--)
	dp[j]=max(dp[j],dp[j-t[i]]+w[i]);
	printf("%d",dp[T]);
	
}

完全背包(未优化)

洛谷P1616
十年OI一场空,遇见yummy见祖宗

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e4+5,M=1e7+5;
int n,m,w[N],v[N],f[M];
signed main(){
	scanf("%lld%lld",&m,&n);
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&w[i],&v[i]);
	for(int i=1;i<=n;i++)
		for(int j=w[i];j<=m;j++)
			f[j]=max(f[j],f[j-w[i]]+v[i]);
	printf("%lld",f[m]);
	return 0;
}

多次背包(未优化)

本校OJ P245

#include<bits/stdc++.h>
using namespace std;
int n,m,dp[100010],v[100010],w[100010],s[100010];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	scanf("%d%d%d",&v[i],&w[i],&s[i]);
	for(int i=1;i<=n;i++)
	for(int j=m;j>=0;j--)
	for(int k=0;k<=s[i];k++)
	if(k*v[i]<=j)  dp[j]=max(dp[j],dp[j-k*v[i]]+w[i]*k);
	printf("%d",dp[m]);	
} 

多重背包的二进制优化

还有一种效率更高的单调队列优化,这里不提到。

for (int i = 1; i <= spe; i++)
        {
            //核心代码
            for (int j = 1; num[i] > j; j <<= 1)//注意j用到二进制位移
            {
                sale[++count] = sale[i] * j;
                wei[count] = wei[i] * j;
                num[i] -= j;
            }
            wei[i] = wei[i] * num[i];
            sale[i] = sale[i] * num[i];
        }
```cpp

分组背包

本校OJ P248

#include<bits/stdc++.h>
using namespace std;
int dp[100010],w[100010],c[100010],num[100010];
int main()
{
	int v,n,t;
	scanf("%d%d%d",&v,&n,&t);
	for(int i=1;i<=n;i++)
	scanf("%d%d%d",&w[i],&c[i],&num[i]);
	for(int i=1;i<=t;i++)
	for(int j=v;j>=0;j--)
	for(int k=1;k<=n;k++)
	if(num[k]==i&&j>=w[k])dp[j]=max(dp[j],dp[j-w[k]]+c[k]);
	printf("%d",dp[v]); 
}

字符串

KMP

LuoguP3375

#include<bits/stdc++.h>
#define ri register int
using namespace std;
char s1[1000100],s2[1000100];
int len1,len2,j;
int kmp[1000100];
int main()
{
	scanf("%s%s",s1+1,s2+1);
	len1=strlen(s1+1);	
	len2=strlen(s2+1);	
	for(ri i=2;i<=len2;i++)
	{
		while(j&&s2[i]!=s2[j+1])
		j=kmp[j];
		if(s2[j+1]==s2[i])	j++;
		kmp[i]=j;
	}
	j=0;
	for(ri i=1;i<=len1;i++)
	{
		while(j>0&&s2[j+1]!=s1[i])	j=kmp[j];
		if(s2[j+1]==s1[i])	j++;
		if(j==len2)
		{
			printf("%d\n",i-len2+1);
			j=kmp[j];
		}
	}
	for(ri i=1;i<=len2;i++)
	printf("%d ",kmp[i]);
} 

数学

欧几里得算法

#include <iostream>
using namespace std;
int gcd(int a, int b)
{
    if (a < b) swap(a, b);
    return b == 0 ? a : gcd(b, a % b);
}
int x, y; 
int main(){
     
    cin >> x >> y;
    cout << gcd(x, y);
    //直接使用STL中的__gcd()同样高效
    return 0;
}

埃氏筛法

Luogu P3912

#include<bits/stdc++.h>
using namespace std;
bool prime[100010];
int main()
{
	int n;
	cin>>n;
	prime[0]=prime[1]=1;
	int maxn=sqrt(n);
	for(int i=2;i<=maxn;i++)
	{
		if(!prime[i])
		for(int j=i*2;j<=n;j+=i)
		prime[j]=1;	
	} 
	for(int i=1;i<=n;i++)
	if(!prime[i])	cout<<i<<' ';
}

欧拉线性筛及欧拉函数

SP5971

#include<bits/stdc++.h>
using namespace std;
bool isp[100010];
int pri[100010],phi[100010],cnt;
int main()
{
	int n;
	cin>>n;
	phi[1]=isp[1]=1;
	//		欧拉线性筛 
	for(int i=1;i<=n;i++)
	{
		if(!isp[i])
		{
			pri[++cnt]=i;
			phi[i]=i-1;	
		}
		for(int j=1;j<=cnt && i*pri[j]<=n;j++)
		{
			isp[i*pri[j]]=1;
			if(i%pri[j])	phi[i*pri[j]]=phi[i]*phi[pri[j]];
			else
			{
				phi[i*pri[j]]=phi[i]*pri[j];
				break;
			}
		}
	}
	for(int i=1;i<=n;i++)
	if(!isp[i])		cout<<i<<' ';
	cout<<endl<<endl;
	for(int i=1;i<=n;i++)
	cout<<phi[i]<<' ';
}

求解逆元的千层套路

保证给出数据一定有逆元的时候才可以用哦
例题

扩展欧几里得

#include<bits/stdc++.h>
using namespace std;
long long a,b;
long long x,y;
void exgcd(long long a,long long b)
{
	if(b==0)
	{
		x=1;
		y=0;
		return ;
	}
	exgcd(b,a%b);
	long long temp=x;
	x=y;
	y=temp-a/b*y;
}
int main()
{
	scanf("%d%d",&a,&b);
	exgcd(a,b);
	x=(x%b+b)%b;
	printf("%d",x);
}

未完待续咯~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值