个人整理ACM模板.docx
- 文档编号:24334631
- 上传时间:2023-05-26
- 格式:DOCX
- 页数:51
- 大小:29.70KB
个人整理ACM模板.docx
《个人整理ACM模板.docx》由会员分享,可在线阅读,更多相关《个人整理ACM模板.docx(51页珍藏版)》请在冰豆网上搜索。
个人整理ACM模板
1.头文件
#define_CRT_SBCURE_NO_DEPRECATE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
usingnamespacestd;
constintmaxn=110;
2.constintINF=0x3f3f3f3f;
经典
1.埃拉托斯特尼筛法
/*
|埃式筛法|
|快速筛选素数|
|16/11/05ztx|
*/
intprime[maxn];
boolis_prime[maxn];
intsieve(intn){
intp=0;
for(inti=0;i<=n;++i)
is_prime[i]=true;
is_prime[0]=is_prime[1]=false;
for(inti=2;i<=n;++i){//注意数组大小是n
if(is_prime[i]){
prime[p++]=i;
for(intj=i+i;j<=n;j+=i)//轻剪枝,j必定是i的倍数
is_prime[j]=false;
}
}
returnp;//返回素数个数
}
2.快速幂
/*
|快速幂|
|16/11/05ztx|
*/
typedeflonglongLL;//视数据大小的情况而定
LLpowerMod(LLx,LLn,LLm)
{
LLres=1;
while(n>0){
if(n&1)//判断是否为奇数,若是则true
res=(res*x)%m;
x=(x*x)%m;
n>>=1;//相当于n/=2;
}
returnres;
}
3.大数模拟
大数加法
/*
|大数模拟加法|
|用string模拟|
|16/11/05ztx,thankstocaojiji|
*/
stringadd1(strings1,strings2)
{
if(s1==""&&s2=="")return"0";
if(s1=="")returns2;
if(s2=="")returns1;
stringmaxx=s1,minn=s2;
if(s1.length() maxx=s2; minn=s1; } inta=maxx.length()-1,b=minn.length()-1; for(inti=b;i>=0;--i){ maxx[a--]+=minn[i]-'0';//a一直在减,额外还要减个'0' } for(inti=maxx.length()-1;i>0;--i){ if(maxx[i]>'9'){ maxx[i]-=10;//注意这个是减10 maxx[i-1]++; } } if(maxx[0]>'9'){ maxx[0]-=10; maxx='1'+maxx; } returnmaxx; } 大数阶乘 /* |大数模拟阶乘| |用数组模拟| |16/12/02ztx| */ #include #include usingnamespacestd; typedeflonglongLL; constintmaxn=100010; intnum[maxn],len; /* 在mult函数中,形参部分: len每次调用函数都会发生改变,n表示每次要乘以的数,最终返回的是结果的长度 tip: 阶乘都是先求之前的(n-1)! 来求n! 初始化Init函数很重要,不要落下 */ voidInit(){ len=1; num[0]=1; } intmult(intnum[],intlen,intn){ LLtmp=0; for(LLi=0;i tmp=tmp+num[i]*n;//从最低位开始,等号左边的tmp表示当前位,右边的tmp表示进位(之前进的位) num[i]=tmp%10;//保存在对应的数组位置,即去掉进位后的一位数 tmp=tmp/10;//取整用于再次循环,与n和下一个位置的乘积相加 } while(tmp){//之后的进位处理 num[len++]=tmp%10; tmp=tmp/10; } returnlen; } intmain(){ Init(); intn; n=1977;//求的阶乘数 for(inti=2;i<=n;++i){ len=mult(num,len,i); } for(inti=len-1;i>=0;--i) printf("%d",num[i]);//从最高位依次输出,数据比较多采用printf输出 printf("\n"); return0; } 4.GCD /* |辗转相除法| |欧几里得算法| |求最大公约数| |16/11/05ztx| */ intgcd(intbig,intsmall) { if(small>big)s,small); inttemp; while(small! =0){//辗转相除法 if(small>big)s,small); temp=big%small; big=small; small=temp; } return(big); } 5.LCM /* |辗转相除法| |欧几里得算法| |求最小公倍数| |16/11/05ztx| */ intgcd(intbig,intsmall) { if(small>big)s,small); inttemp; while(small! =0){//辗转相除法 if(small>big)s,small); temp=big%small; big=small; small=temp; } return(big); } 6.全排列 /* |求1到n的全排列,有条件| |16/11/05ztx,thankstowangqiqi| */ voidPern(intlist[],intk,intn){//k表示前k个数不动仅移动后面n-k位数 if(k==n-1){ for(inti=0;i printf("%d",list[i]); } printf("\n"); }else{ for(inti=k;i s[k],list[i]); Pern(list,k+1,n); s[k],list[i]); } } } 7.二分搜索 /* |二分搜索| |要求: 先排序| |16/11/05ztx,thankstowangxiaocai| */ //left为最开始元素,right是末尾元素的下一个数,x是要找的数 intbsearch(int*A,intleft,intright,intx){ intm; while(left m=left+(right-left)/2; if(A[m]>=x)right=m;elseleft=m+1; //如果要替换为upper_bound,改为: if(A[m]<=v)x=m+1;elsey=m; } returnleft; } /* 最后left==right 如果没有找到135577找6,返回7 如果找有多少的x,可以用lower_bound查找一遍,upper_bound查找一遍,下标相减 C++自带的lower_bound(a,a+n,x)返回数组中最后一个x的下一个数的地址 upper_bound(a,a+n,x)返回数组中第一个x的地址 如果a+n内没有找到x或x的下一个地址,返回a+n的地址 lower_bound(a,a+n,x)-upper_bound(a,a+n,x)返回数组中x的个数 */ 数据结构 并查集 8.并查集 /* |合并节点操作| |16/11/05ztx,thankstochaixiaojun| */ intfather[maxn];//储存i的father父节点 voidmakeSet(){ for(inti=0;i father[i]=i; } intfindRoot(intx){//迭代找根节点 introot=x;//根节点 while(root! =father[root]){//寻找根节点 root=father[root]; } while(x! =root){ inttmp=father[x]; father[x]=root;//根节点赋值 x=tmp; } returnroot; } voidUnion(intx,inty){//将x所在的集合和y所在的集合整合起来形成一个集合。 inta,b; a=findRoot(x); b=findRoot(y); father[a]=b;//y连在x的根节点上或father[b]=a为x连在y的根节点上; } /* 在findRoot(x)中: 路径压缩迭代最优版 关键在于在路径上的每个节点都可以直接连接到根上 */ 图论 MST 最小生成树 Kruskal 9.克鲁斯卡尔算法 /* |Kruskal算法| |适用于稀疏图求最小生成树| |16/11/05ztxthankstowangqiqi| */ /* 第一步: 点、边、加入vector,把所有边按从小到大排序 第二步: 并查集部分+下面的code */ voidKruskal(){ ans=0; for(inti=0;i if(Find(edge[i].a)! =Find(edge[i].b)){ Union(edge[i].a,edge[i].b); ans+=edge[i].len; } } } Prim 10.普里姆算法 /* |Prim算法| |适用于稠密图求最小生成树| |堆优化版,时间复杂度: O(elgn)| |16/11/05ztx,thankstochaixiaojun| */ structnode{ intv,len; node(intv=0,intlen=0): v(v),len(len){} booloperator<(constnode&a)const{//加入队列的元素自动按距离从小到大排序 returnlen>a.len; } }; vector intvis[maxn]; intdis[maxn]; voidinit(){ for(inti=0;i G[i].clear(); dis[i]=INF; vis[i]=false; } } intPrim(ints){ priority_queue intans=0; Q.push(node(s,0));//起点加入队列 while(! Q.empty()){ nodenow=Q.top();Q.pop();//取出距离最小的点 intv=now.v; if(vis[v])continue;//同一个节点,可能会推入2次或2次以上队列,这样第一个被标记后,剩下的需要直接跳过。 vis[v]=true;//标记一下 ans+=now.len; for(inti=0;i intv2=G[v][i].v; intlen=G[v][i].len; if(! vis[v2]&&dis[v2]>len){ dis[v2]=len; Q.push(node(v2,dis[v2]));//更新的点加入队列并排序 } } } returnans; } Bellman-Ford 单源最短路 Dijkstra 11.迪杰斯特拉算法 /* |Dijkstra算法| |适用于边权为正的有向图或者无向图| |求从单个源点出发,到所有节点的最短路| |优化版: 时间复杂度O(elbn)| |16/11/05ztx,thankstochaixiaojun| */ structnode{ intv,len; node(intv=0,intlen=0): v(v),len(len){} booloperator<(constnode&a)const{//距离从小到大排序 returnlen>a.len; } }; vector boolvis[maxn]; intdis[maxn]; voidinit(){ for(inti=0;i G[i].clear(); vis[i]=false; dis[i]=INF; } } intdijkstra(ints,inte){ priority_queue Q.push(node(s,0));//加入队列并排序 dis[s]=0; while(! Q.empty()){ nodenow=Q.top();//取出当前最小的 Q.pop(); intv=now.v; if(vis[v])continue;//如果标记过了,直接continue vis[v]=true; for(inti=0;i intv2=G[v][i].v; intlen=G[v][i].len; if(! vis[v2]&&dis[v2]>dis[v]+len){ dis[v2]=dis[v]+len; Q.push(node(v2,dis[v2])); } } } returndis[e]; } SPFA 12.最短路径快速算法(ShortestPathFasterAlgorithm) /* |SPFA算法| |队列优化| |可处理负环| */ vector boolinqueue[maxn]; intdist[maxn]; voidInit() { for(inti=0;i G[i].clear(); dist[i]=INF; } } intSPFA(ints,inte) { intv1,v2,weight; queue memset(inqueue,false,sizeof(inqueue));//标记是否在队列中 memset(cnt,0,sizeof(cnt));//加入队列的次数 dist[s]=0; Q.push(s);//起点加入队列 inqueue[s]=true;//标记 while(! Q.empty()){ v1=Q.front(); Q.pop(); inqueue[v1]=false;//取消标记 for(inti=0;i v2=G[v1][i].vex; weight=G[v1][i].weight; if(dist[v2]>dist[v1]+weight){//松弛操作 dist[v2]=dist[v1]+weight; if(inqueue[v2]==false){//再次加入队列 inqueue[v2]=true; //cnt[v2]++;//判负环 //if(cnt[v2]>n)return-1; Q.push(v2); }}} } returndist[e]; } /* 不断的将s的邻接点加入队列,取出不断的进行松弛操作,直到队列为空 如果一个结点被加入队列超过n-1次,那么显然图中有负环 */ Floyd-Warshall 13.弗洛伊德算法 /* |Floyd算法| |任意点对最短路算法| |求图中任意两点的最短距离的算法| */ for(inti=0;i for(intj=0;j scanf("%lf",&dis[i][j]); } for(intk=0;k for(inti=0;i for(intj=0;j dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]); } } } 二分图 14.染色法 /* |交叉染色法判断二分图| |16/11/05ztx| */ intbipartite(ints){ intu,v; queue color[s]=1; Q.push(s); while(! Q.empty()){ u=Q.front(); Q.pop(); for(inti=0;i v=G[u][i]; if(color[v]==0){ color[v]=-color[u]; Q.push(v); } elseif(color[v]==color[u]) return0; } } return1; } 15..匈牙利算法 /* |求解最大匹配问题| |递归实现| |16/11/05ztx| */ vector boolinpath[maxn];//标记 intmatch[maxn];//记录匹配对象 voidinit() { memset(match,-1,sizeof(match)); for(inti=0;i G[i].clear(); } } boolfindpath(intk){ for(inti=0;i intv=G[k][i]; if(! inpath[v]){ inpath[v]=true; if(match[v]==-1||findpath(match[v])){//递归 match[v]=k;//即匹配对象是“k妹子”的 returntrue; } } } returnfalse; } voidhungary(){ intcnt=0; for(inti=1;i<=m;i++){//m为需要匹配的“妹子”数 memset(inpath,false,sizeof(inpath));//每次都要初始化 if(findpath(i))cnt++; } cout< } /* |求解最大匹配问题| |dfs实现| |16/11/05ztx| */ intv1,v2; boolMap[501][501]; boolvisit[501]; intlink[501]; intresult; booldfs(intx){ for(inty=1;y<=v2;++y){ if(Map[x][y]&&! visit[y]){ visit[y]=true; if(link[y]==0||dfs(link[y])){ link[y]=x; returntrue; }}} returnfalse; } voidSearch(){ for(intx
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 个人 整理 ACM 模板