个人整理 ACM 模板.docx

上传人:b****6 文档编号:6620491 上传时间:2023-01-08 格式:DOCX 页数:44 大小:29.78KB
下载 相关 举报
个人整理 ACM 模板.docx_第1页
第1页 / 共44页
个人整理 ACM 模板.docx_第2页
第2页 / 共44页
个人整理 ACM 模板.docx_第3页
第3页 / 共44页
个人整理 ACM 模板.docx_第4页
第4页 / 共44页
个人整理 ACM 模板.docx_第5页
第5页 / 共44页
点击查看更多>>
下载资源
资源描述

个人整理 ACM 模板.docx

《个人整理 ACM 模板.docx》由会员分享,可在线阅读,更多相关《个人整理 ACM 模板.docx(44页珍藏版)》请在冰豆网上搜索。

个人整理 ACM 模板.docx

个人整理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)swap(big,small);

inttemp;

while(small!

=0){//辗转相除法

if(small>big)swap(big,small);

temp=big%small;

big=small;

small=temp;

}

return(big);

}

5.LCM

/*

|辗转相除法|

|欧几里得算法|

|求最小公倍数|

|16/11/05ztx|

*/

intgcd(intbig,intsmall)

{

if(small>big)swap(big,small);

inttemp;

while(small!

=0){//辗转相除法

if(small>big)swap(big,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

swap(list[k],list[i]);

Pern(list,k+1,n);

swap(list[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;

}

};

vectorG[maxn];

intvis[maxn];

intdis[maxn];

voidinit(){

for(inti=0;i

G[i].clear();

dis[i]=INF;

vis[i]=false;

}

}

intPrim(ints){

priority_queueQ;//定义优先队列

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;

}

};

vectorG[maxn];

boolvis[maxn];

intdis[maxn];

voidinit(){

for(inti=0;i

G[i].clear();

vis[i]=false;

dis[i]=INF;

}

}

intdijkstra(ints,inte){

priority_queueQ;

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算法|

|队列优化|

|可处理负环|

*/

vectorG[maxn];

boolinqueue[maxn];

intdist[maxn];

voidInit()

{

for(inti=0;i

G[i].clear();

dist[i]=INF;

}

}

intSPFA(ints,inte)

{

intv1,v2,weight;

queueQ;

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;

queueQ;

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|

*/

vectorG[maxn];

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;

}}}

return

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1