ACM比赛模板
ACM程序设计-赛题样例
ACM程序设计-赛题样例座位调整题目描述:百度办公区里到处摆放着各种各样的零食。
百度人力资源部的调研发现,员工如果可以在自己喜欢的美食旁边工作,工作效率会大大提高。
因此,百度决定进行一次员工座位的大调整。
调整的方法如下:1 .首先将办公区按照各种零食的摆放分成 N 个不同的区域。
(例如:可乐区,饼干区,牛奶区等等)。
2 .每个员工对不同的零食区域有不同的喜好程度(喜好程度度的范围为 1 — 100 的整数,喜好程度越大表示该员工越希望被调整到相应的零食区域)。
3 .由于每个零食区域可以容纳的员工数量有限,人力资源部希望找到一个最优的调整方案令到总的喜好程度最大。
数据输入:第一行包含两个整数 N , M ,( 1<=N ,M<=300 )。
分别表示 N 个区域和 M 个员工。
第二行是 N 个整数构成的数列 a ,其中 a[i] 表示第 i 个区域可以容纳的员工数,(1<=a[i]<=M , a[1]+a[2]+..+a[N]=M) 。
紧接着是一个 M*N 的矩阵 P , P ( i , j )表示第 i 个员工对第 j 个区域的喜好度。
答案输出:对于每个测试数据,输出可以达到的最大的喜好程度。
输入样例3 31 1 1100 50 25100 50 25100 50 25输出样例175#include<stdio.h>void main(){int n,m,l=0,i,j,s,t,sum=0;int a[100],p[100][100],b[100],c[100];for(i=0;i<100;i++){a[i]=0,c[i]=0,b[i]=0;for(j=0;j<100;j++)p[i][j]=0;}scanf("%d %d",&n,&m);for(i=0;i<n;i++){scanf("%d ",&a[i]);}for(i=0;i<n;i++){for(j=0;j<m;j++){scanf("%d",&p[i][j]);}}i=0;frist:if(i>=m)goto finish;if(l>0){for(s=0;s<l;s++){t=c[s];for(j=0;j<m;j++){p[t][j]=0;}}}for(s=0;s<m;s++){b[s]=0;}for(s=0;s<n;s++){b[s]=p[s][i];}for(s=0;s<n-1;s++){for(j=0;j<n-1-s;j++){if(b[j]<b[j+1]){t=b[j];b[j]=b[j+1]; b[j+1]=t;}}}// printf("%d\t",b[0]); // test++;for(s=0;s<a[i];s++){sum=sum+b[s];}s=0;sec:if(s>=a[i]){i++;goto frist;}for(t=0;t<n;t++){if(b[s]==p[t][i]){c[l]=t;l++;break;else continue;}s++;goto sec;finish:// printf("\n");printf("最大的喜好程度为:%d\n",sum);// printf("%d",test);}#include<stdio.h>#include<stdlib.h>void main(){int s,t,u,v,w,x,y,z,sum=0,a[20],b[20][20],c[20],d[20],sumx[80],*p=sumx,max; scanf("%d%d",&x,&y);for(z=0;z<x;z++){scanf("%d",&a[z]);}for(z=0;z<y;z++){c[z]=z;d[z]=z;}for(w=0;w<y;w++){for(z=0;z<x;z++){scanf("%d",&b[w][z]);}}sum=0;for(z=0;z<y;z++){sum+=b[0][z];for(w=z;w<y-1;w++)d[w]=d[w+1];}for(w=0;w<y-1;w++){s=d[w];sum+=b[1][s];for(v=w;v<y-2;v++){d[v]=d[v+1];}for(u=0;u<y-2;u++){s=d[u];sum+=b[1][s];for(t=u;t<y-3;t++){d[u]=d[u+1];}for(t=0;t<y-3;t++){s=d[t];sum+=b[2][s];for(z=0;z<y;z++){d[20]=c[20];}}*p=sum;sum=0;p++;}}}t=1;max=sumx[0];while(sumx[t]){if(sumx[t]>max)max=sumx[t];t++;}printf("%d\n",max);}#include<stdio.h>#include<malloc.h>int main(int argc,char** argv){int N,M,*a,**p,*temp,i,j,k,max=0;;printf("Please input area and staff num:");scanf("%d %d",&N,&M);a=(int*)malloc(sizeof(int)*N);printf("\nPlease input staff num of each area:");for(i=0;i<N;i++)scanf("%d",&a[i]);p=(int**)malloc(sizeof(int)*N);printf("\nPlease input like:");for(i=0;i<M;i++)p[i]=(int*)malloc(sizeof(int)*M);for(i=0;i<M;i++)for(j=0;j<N;j++)scanf("%d",&p[i][j]);temp=(int*)malloc(sizeof(int)*M);for(i=0;i<N;i++){if(i<N-1){for(j=0;j<M;j++){k=i+1;temp[j]=0;while(k<N){temp[j]+=p[j][i]-p[j][k];k++;}}int temp1,temp2;while(a[i]){temp1=-101;temp2=0;for(j=0;j<M;j++){if(temp[j]>temp1){temp1=temp[j];temp2=j;}}max+=p[temp2][i];printf("%d %d %d\n",p[temp2][i],temp2,i);for(int m=0;m<N;m++)p[temp2][m]=-101;printf("\n");for(int q=0;q<M;q++){for(int w=0;w<N;w++){printf(" %d ",p[q][w]);}printf("\n");}temp[temp2]=-101;a[i]--;}}else{int temp3,temp4;while(a[i]){temp3=-101;temp4=0;for(j=0;j<M;j++){if(p[j][i]>temp3){temp3=p[j][i];temp4=j;}}max+=p[temp4][i];printf("%d %d %d\n",p[temp4][i],temp4,i);for(int m=0;m<N;m++)p[temp4][m]=-101;printf("\n");for(int q=0;q<M;q++){for(int w=0;w<N;w++){printf(" %d ",p[q][w]);}printf("\n");}temp[temp4]=-101;a[i]--;}}}printf("Max=%d\n",max);return0;//Your program should return 0 on normal termination.}蝈蝈式的记分内容描述:蝈蝈小朋友刚刚学会了 0-9 这十个数字 , 也跟爸爸妈妈来参加百度每周进行的羽毛球活动。
ACM模板
ACM程序设计大赛(校级)
Problem A ISBN号码Description每一本正式出版的图书都有一个ISBN号码之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。
ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔之后的五位数字代表该书在该出版社的编号;最后一位为识别码。
识别码计算方法如下:首位数字乘以1加上次位数字乘以2……以此类推,所得的结果mod 11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。
例如ISBN号码0-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2.,……,9,再求和,即0×1+6×2+……+2×9=158,然后取158 mod 11 的结果4作为识别码。
你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出你认为是正确的ISBN号码。
Input输入只有一行,是一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。
Output输出共一行,假如输入的ISBN号码的识别码正确,那么输出“Right”,否则,按照规定格式,输出正确的ISBN号码(包括分隔符“-”)。
Sample1 Input0-670-82162-4Sample2 Input0-670-82162-0Sample1 OutputRightSample2 Output0-670-82162-4Problem B 子串清除Description我们定义字符串A是字符串B的子串当且仅当我们能在B串中找到A串。
现在给你一个字符串A,和另外一个字符串B,要你每次从B串中从左至右找第一个A串,并从B串中删除它,直到A串不为B串的子串,问你需要进行几次删除操作。
ACM程序竞赛计算几何超全模板
/*计算几何目录㈠点的基本运算1. 平面上两点之间距离12. 判断两点是否重合13. 矢量叉乘14. 矢量点乘25. 判断点是否在线段上26. 求一点饶某点旋转后的坐标27. 求矢量夹角2㈡线段及直线的基本运算1. 点与线段的关系32. 求点到线段所在直线垂线的垂足43. 点到线段的最近点44. 点到线段所在直线的距离45. 点到折线集的最近距离46. 判断圆是否在多边形内57. 求矢量夹角余弦58. 求线段之间的夹角59. 判断线段是否相交610.判断线段是否相交但不交在端点处611.求线段所在直线的方程612.求直线的斜率713.求直线的倾斜角714.求点关于某直线的对称点715.判断两条直线是否相交及求直线交点716.判断线段是否相交,如果相交返回交点7㈢多边形常用算法模块1. 判断多边形是否简单多边形82. 检查多边形顶点的凸凹性93. 判断多边形是否凸多边形94. 求多边形面积95. 判断多边形顶点的排列方向,方法一106. 判断多边形顶点的排列方向,方法二107. 射线法判断点是否在多边形内108. 判断点是否在凸多边形内119. 寻找点集的graham算法1210.寻找点集凸包的卷包裹法1311.判断线段是否在多边形内1412.求简单多边形的重心1513.求凸多边形的重心1714.求肯定在给定多边形内的一个点1715.求从多边形外一点出发到该多边形的切线1816.判断多边形的核是否存在19㈣圆的基本运算1 .点是否在圆内202 .求不共线的三点所确定的圆21㈤矩形的基本运算1.已知矩形三点坐标,求第4点坐标22㈥常用算法的描述22㈦补充1.两圆关系:242.判断圆是否在矩形内:243.点到平面的距离:254.点是否在直线同侧:255.镜面反射线:256.矩形包含:267.两圆交点:278.两圆公共面积:289. 圆和直线关系:2910. 内切圆:3011. 求切点:3112. 线段的左右旋:3113.公式:32*//* 需要包含的头文件*/#include <cmath >/* 常用的常量定义*/const double INF = 1E200const double EP = 1E-10const int MAXV = 300const double PI = 3.14159265/* 基本几何结构*/struct POINT{double x;double y;POINT(double a=0, double b=0) { x=a; y=b;} //constructor};struct LINESEG{POINT s;POINT e;LINESEG(POINT a, POINT b) { s=a; e=b;}LINESEG() { }};struct LINE // 直线的解析方程a*x+b*y+c=0 为统一表示,约定a >= 0{double a;double b;double c;LINE(double d1=1, double d2=-1, double d3=0) {a=d1; b=d2; c=d3;}};/*********************** ** 点的基本运算** ***********************/double dist(POINT p1,POINT p2) // 返回两点之间欧氏距离{return( sqrt( (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y) ) );}bool equal_point(POINT p1,POINT p2) // 判断两个点是否重合{return ( (abs(p1.x-p2.x)<EP)&&(abs(p1.y-p2.y)<EP) );}/****************************************************************************** r=multiply(sp,ep,op),得到(sp-op)和(ep-op)的叉积r>0:ep在矢量opsp的逆时针方向;r=0:opspep三点共线;r<0:ep在矢量opsp的顺时针方向******************************************************************************* /double multiply(POINT sp,POINT ep,POINT op){return((sp.x-op.x)*(ep.y-op.y)-(ep.x-op.x)*(sp.y-op.y));}/*r=dotmultiply(p1,p2,op),得到矢量(p1-op)和(p2-op)的点积,如果两个矢量都非零矢量r<0:两矢量夹角为锐角;r=0:两矢量夹角为直角;r>0:两矢量夹角为钝角******************************************************************************* /double dotmultiply(POINT p1,POINT p2,POINT p0){return ((p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y));}/****************************************************************************** 判断点p是否在线段l上条件:(p在线段l所在的直线上) && (点p在以线段l为对角线的矩形内)******************************************************************************* /bool online(LINESEG l,POINT p){return( (multiply(l.e,p,l.s)==0) &&( ( (p.x-l.s.x)*(p.x-l.e.x)<=0 )&&( (p.y-l.s.y)*(p.y-l.e.y)<=0 ) ) ); }// 返回点p以点o为圆心逆时针旋转alpha(单位:弧度)后所在的位置POINT rotate(POINT o,double alpha,POINT p){POINT tp;p.x-=o.x;p.y-=o.y;tp.x=p.x*cos(alpha)-p.y*sin(alpha)+o.x;tp.y=p.y*cos(alpha)+p.x*sin(alpha)+o.y;return tp;}/* 返回顶角在o点,起始边为os,终止边为oe的夹角(单位:弧度)角度小于pi,返回正值角度大于pi,返回负值可以用于求线段之间的夹角原理:r = dotmultiply(s,e,o) / (dist(o,s)*dist(o,e))r'= multiply(s,e,o)r >= 1 angle = 0;r <= -1 angle = -PI-1<r<1 && r'>0 angle = arccos(r)-1<r<1 && r'<=0 angle = -arccos(r)*/double angle(POINT o,POINT s,POINT e){double cosfi,fi,norm;double dsx = s.x - o.x;double dsy = s.y - o.y;double dex = e.x - o.x;double dey = e.y - o.y;cosfi=dsx*dex+dsy*dey;norm=(dsx*dsx+dsy*dsy)*(dex*dex+dey*dey);cosfi /= sqrt( norm );if (cosfi >= 1.0 ) return 0;if (cosfi <= -1.0 ) return -3.1415926;fi=acos(cosfi);if (dsx*dey-dsy*dex>0) return fi; // 说明矢量os 在矢量oe的顺时针方向return -fi;}/*****************************\* ** 线段及直线的基本运算** *\*****************************//* 判断点与线段的关系,用途很广泛本函数是根据下面的公式写的,P是点C到线段AB所在直线的垂足AC dot ABr = ---------||AB||^2(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)= -------------------------------L^2r has the following meaning:r=0 P = Ar=1 P = Br<0 P is on the backward extension of ABr>1 P is on the forward extension of AB0<r<1 P is interior to AB*/double relation(POINT p,LINESEG l){LINESEG tl;tl.s=l.s;tl.e=p;return dotmultiply(tl.e,l.e,l.s)/(dist(l.s,l.e)*dist(l.s,l.e));}// 求点C到线段AB所在直线的垂足PPOINT perpendicular(POINT p,LINESEG l){double r=relation(p,l);POINT tp;tp.x=l.s.x+r*(l.e.x-l.s.x);tp.y=l.s.y+r*(l.e.y-l.s.y);return tp;}/* 求点p到线段l的最短距离,并返回线段上距该点最近的点np注意:np是线段l上到点p最近的点,不一定是垂足*/double ptolinesegdist(POINT p,LINESEG l,POINT &np){double r=relation(p,l);if(r<0){np=l.s;return dist(p,l.s);}if(r>1){np=l.e;return dist(p,l.e);}np=perpendicular(p,l);return dist(p,np);}// 求点p到线段l所在直线的距离,请注意本函数与上个函数的区别double ptoldist(POINT p,LINESEG l){return abs(multiply(p,l.e,l.s))/dist(l.s,l.e);}/* 计算点到折线集的最近距离,并返回最近点.注意:调用的是ptolineseg()函数*/double ptopointset(int vcount,POINT pointset[],POINT p,POINT &q) {int i;double cd=double(INF),td;LINESEG l;POINT tq,cq;for(i=0;i<vcount-1;i++)l.s=pointset[i];l.e=pointset[i+1];td=ptolinesegdist(p,l,tq);if(td<cd){cd=td;cq=tq;}}q=cq;return cd;}/* 判断圆是否在多边形内.ptolineseg()函数的应用2 */bool CircleInsidePolygon(int vcount,POINT center,double radius,POINT polygon[]){POINT q;double d;q.x=0;q.y=0;d=ptopointset(vcount,polygon,center,q);if(d<radius||fabs(d-radius)<EP)return true;elsereturn false;}/* 返回两个矢量l1和l2的夹角的余弦(-1 --- 1)注意:如果想从余弦求夹角的话,注意反余弦函数的定义域是从0到pi */double cosine(LINESEG l1,LINESEG l2){return (((l1.e.x-l1.s.x)*(l2.e.x-l2.s.x) +(l1.e.y-l1.s.y)*(l2.e.y-l2.s.y))/(dist(l1.e,l1.s)*dist(l2.e,l2.s))) );}// 返回线段l1与l2之间的夹角单位:弧度范围(-pi,pi)double lsangle(LINESEG l1,LINESEG l2){POINT o,s,e;o.x=o.y=0;s.x=l1.e.x-l1.s.x;s.y=l1.e.y-l1.s.y;e.x=l2.e.x-l2.s.x;e.y=l2.e.y-l2.s.y;return angle(o,s,e);// 如果线段u和v相交(包括相交在端点处)时,返回true////判断P1P2跨立Q1Q2的依据是:( P1 - Q1 ) ×( Q2 - Q1 ) * ( Q2 - Q1 ) ×( P2 - Q1 ) >= 0。
ACM_JAVA(ACM模板)
2/25
28 return new T(key, val, t.p, t.left, t.right); 29 } 30 T remove(T t, int key) { 31 32 if (t == null) return null; if (key < t.key) return t.change(remove(t.left, key), t.right);
University of Tokyo
2 13 int res = 0; for (int i = t; i > 0; i -= i & -i) { res += vs[i]; } return res; } //[0,i] k int get(int k) { i
1/25
1
1 import static ng.Math.*; 2 import static java.util.Arrays.*; 3 import java.io.*; 4 import java.util.*; 5 6 public class Main { 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 } } static boolean LOCAL = System.getSecurityManager() == null; Scanner sc = new Scanner(System.in); void run() { } void debug(Object...os) { System.err.println(deepToString(os)); } public static void main(String[] args) { if (LOCAL) { try { System.setIn(new FileInputStream("in.txt")); } catch (Throwable e) { LOCAL = false; } } new Main().run();
[IT计算机]山东大学ACM模板_图论
图论1.最短路径 (4)1)Dijkstra之优雅stl (4)2)Dijkstra__模拟数组 (4)3)Dijkstra阵 (5)4)SPFA优化 (6)5)差分约束系统 (7)2.K短路 (7)1)Readme (7)2)K短路_无环_Astar (7)3)K短路_无环_Yen (10)4)K短路_无环_Yen_字典序 (12)5)K短路_有环_Astar (15)6)K短路_有环_Yen (17)7)次短路经&&路径数 (20)3.连通分支 (21)1)图论_SCC (21)2)2-sat (23)3)BCC (25)4.生成树 (27)1)Kruskal (27)2)Prim_MST是否唯一 (28)3)Prim阵 (29)4)度限制MST (30)5)次小生成树 (34)6)次小生成树_阵 (36)7)严格次小生成树 (37)8)K小生成树伪代码 (41)9)MST计数_连通性状压_NOI07 (41)10)曼哈顿MST (43)11)曼哈顿MST_基数排序 (46)12)生成树变MST_sgu206 (49)13)生成树计数 (52)14)最小生成树计数 (53)15)最小树形图 (56)16)图论_最小树形图_double_poj3壹64 (58)5.最大流 (60)1)Edmonds_Karp算法 (60)2)SAP邻接矩阵 (61)3)SAP模拟数组 (62)4)SAP_BFS (63)5)sgu壹85_AC(两条最短路径) (64)6)有上下界的最大流—数组模拟 (67)6.费用流 (69)1)费用流_SPFA_增广 (69)2)费用流_SPFA_消圈 (70)3)ZKW数组模拟 (72)7.割 (73)1)最大权闭合图 (73)2)最大密度子图 (73)3)二分图的最小点权覆盖 (74)4)二分图的最大点权独立集 (75)5)无向图最小割_Stoer-Wagner算法 (75)6)无向图最大割 (76)7)无向图最大割(壹6ms) (76)8.二分图 (78)1)二分图最大匹配Edmonds (78)2)必须边 (79)3)最小路径覆盖(路径不相交) (79)4)二分图最大匹配HK (80)5)KM算法_朴素_O(n4) (81)6)KM算法_slack_O(n3) (82)7)点BCC_二分判定_(2942圆桌骑士) (84)8)二分图多重匹配 (86)9)二分图判定 (88)10)最小路径覆盖(带权) (89)9.一般图匹配 (90)1)带花树_表 (90)2)带花树_阵 (93)10.各种回路 (96)1)CPP_无向图 (96)2)TSP_双调欧几里得 (97)3)哈密顿回路_dirac (98)4)哈密顿回路_竞赛图 (100)5)哈密顿路径_竞赛图 (102)6)哈密顿路径_最优&状压 (102)11.分治树 (104)1)分治树_路径不经过超过K个标记节点的最长路径 (104)2)分治树_路径和不超过K的点对数 (107)3)分治树_树链剖分_Count_hnoi壹036 (109)4)分治树_QTree壹_树链剖分 (113)5)分治树_POJ3237(QTree壹升级)_树链剖分 (117)6)分治树_QTree2_树链剖分 (122)7)Qtree3 (125)8)分治树_QTree3(2)_树链剖分 (128)9)分治树_QTree4_他人的 (130)10)分治树_QTree5_无代码 (135)12.经典问题 (135)1)欧拉回路_递归 (135)2)欧拉回路_非递归 (136)3)同构_树 (137)4)同构_无向图 (140)5)同构_有向图 (141)6)弦图_表 (143)7)弦图_阵 (147)8)最大团_朴素 (149)9)最大团_快速 (149)10)极大团 (150)11)havel定理 (151)12)Topological (151)13)LCA (152)14)LCA2RMQ (154)15)树中两点路径上最大-最小边_Tarjan扩展 (157)16)树上的最长路径 (160)17)floyd最小环 (161)18)支配集_树 (162)19)prufer编码_树的计数 (164)20)独立集_支配集_匹配 (165)21)最小截断 (168)最短路径Dijkstra之优雅stl#include <queue>using namespace std;#define maxn 壹000struct Dijkstra {typedef pair<int, int> T; //first: 权值,second: 索引vector<T> E[maxn]; //边int d[maxn]; //最短的路径int p[maxn]; //父节点priority_queue<T, vector<T>, greater<T> > q;void clearEdge() {for(int i = 0; i < maxn; i ++)E[i].clear();}void addEdge(int i, int j, int val) {E[i].push_back(T(val, j));}void dijkstra(int s) {memset(d, 壹27, sizeof(d));memset(p, 255, sizeof(p));while(!q.empty()) q.pop();int u, du, v, dv;d[s] = 0;p[s] = s;q.push(T(0, s));while (!q.empty()) {u = q.top().second;du = q.top().first;q.pop();if (d[u] != du) continue;for (vector<T>::iterator it=E[u].begin();it!=E[u].end(); it++){ v = it->second;dv = du + it->first;if (d[v] > dv) {d[v] = dv;p[v] = u;q.push(T(dv, v));}}}}};Dijkstra__模拟数组typedef pair<int,int> T;struct Nod {int b, val, next;void init(int b, int val, int next) {th(b); th(val); th(next);}};struct Dijkstra {Nod buf[maxm]; int len; //资源int E[maxn], n; //图int d[maxn]; //最短距离void init(int n) {th(n);memset(E, 255, sizeof(E));len = 0;}void addEdge(int a, int b, int val) {buf[len].init(b, val, E[a]);E[a] = len ++;}void solve(int s) {static priority_queue<T, vector<T>, greater<T> > q;while(!q.empty()) q.pop();memset(d, 63, sizeof(d));d[s] = 0;q.push(T(0, s));int u, du, v, dv;while(!q.empty()) {u = q.top().second;du = q.top().first;q.pop();if(du != d[u]) continue;for(int i = E[u]; i != -壹; i = buf[i].next) {v = buf[i].b;dv = du + buf[i].val;if(dv < d[v]) {d[v] = dv;q.push(T(dv, v));}}}}};Dijkstra阵//Dijkstra邻接矩阵,不用heap!#define maxn 壹壹0const int inf = 0x3f3f3f3f;struct Dijkstra {int E[maxn][maxn], n; //图,须手动传入!int d[maxn], p[maxn]; //最短路径,父亲void init(int n) {this->n = n;memset(E, 63, sizeof(E));}void solve(int s) {static bool vis[maxn];memset(vis, 0, sizeof(vis));memset(d, 63, sizeof(d));memset(p, 255, sizeof(p));d[s] = 0;while(壹) {int u = -壹;for(int i = 0; i < n; i ++) {if(!vis[i] && (u==-壹||d[i]<d[u])) {u = i;}}if(u == -壹 || d[u]==inf) break;vis[u] = true;for(int v = 0; v < n; v ++) {if(d[u]+E[u][v] < d[v]) {d[v] = d[u]+E[u][v];p[v] = u;}}}}} dij;SPFA优化/*** 以下程序加上了vis优化,但没有加slf和lll优化(似乎效果不是很明显)* 下面是这两个优化的教程,不难实现----------------------------------SPFA的两个优化该日志由 zkw 发表于 2009-02-壹3 09:03:06SPFA 与堆优化的 Dijkstra 的速度之争不是一天两天了,不过从这次 USACO 月赛题来看,SPFA 用在分层图上会比较慢。
github acm竞赛模板 -回复
github acm竞赛模板-回复什么是ACM竞赛模板?解答:ACM竞赛模板是一种常用的编程竞赛工具,主要用于帮助参赛选手快速编写算法和代码。
ACM竞赛模板包含了常见的数据结构、算法和代码片段,方便选手在比赛中快速实现题目要求。
一步一步回答:1. ACME竞赛模板是什么?ACM竞赛模板是一个综合性的编程工具包,针对ACM(Association for Computing Machinery)计算机竞赛而设计。
它包含了常见的数据结构(如栈、队列、链表、堆等)和常用的算法(如排序、查找、递归等),旨在帮助参赛选手快速编写高效的代码解决问题。
2. ACM竞赛模板有哪些特点?ACM竞赛模板的特点主要有以下几个方面:- 综合性:ACM竞赛模板包含了各种常用的数据结构和算法,如树、图、并查集、动态规划等。
选手可以根据题目要求选择适当的数据结构和算法进行实现。
- 高效性:ACM竞赛模板中的算法和代码片段经过优化,具有较高的执行效率。
这对于竞赛中的时间限制非常重要。
- 易用性:ACM竞赛模板的代码清晰、简洁,采用了规范的命名和注释,方便选手理解和使用。
- 可扩展性:ACM竞赛模板是一个基础框架,选手可以根据具体需求进行扩展和修改,以适应不同的竞赛题目。
3. ACM竞赛模板如何使用?使用ACM竞赛模板可以遵循以下步骤:- 下载模板:从GitHub或其他代码库中下载ACM竞赛模板的代码文件。
- 配置环境:根据模板的要求配置编程环境,例如C++或Java的编译器。
- 阅读文档:阅读ACM竞赛模板的说明文档,了解各个函数和数据结构的使用方法和参数说明。
- 编写代码:根据题目要求,在模板的基础上编写相应的算法和代码,实现题目要求。
可以根据需要引入模板中的各个函数和数据结构。
- 调试测试:对编写的代码进行调试和测试,确保功能正确性。
可以使用示例输入数据和预期输出进行测试。
- 提交代码:将编写的代码提交到竞赛平台或评审者处,等待评测结果。
ACM模板4
免费模板~~~2010 ACM程序竞赛模板浙江省第七届大学生程序设计竞赛英文队名:Oh,Jack&Rose中文队名:潘多拉星球暴力AC联盟哈嘻嘟2010年4月17日目录一、图论 (1)1.1.最小生成树类prim算法 (1)1.2.拓扑排序 (4)1.3.最短源路径Folyd实现 (5)1.4.关键路径实现算法 (6)1.5.二分图最大匹配的匈牙利算法 (7)1.6.并查集 (9)二、动规 (10)2.1.求最长子序列 (10)2.2.求解最长升序列长度及子序列 (12)2.3.完全背包问题 (13)2.4.0-1背包问题 (14)2.5.母函数DP算法求组合数 (14)2.6.滚动数组求回文串问题 (17)三、贪心 (18)3.1.时间安排问题 (18)3.2.求最大子段和 (19)3.3.贪心求最少非递减序列数 (20)四、数论 (21)4.1.简单求Cnk问题 (21)4.2.巧求阶乘位数 (21)4.3.线性算法求素数 (22)五、其他 (22)5.1.采用位操作递归求解示例 (22)5.2.Stack和Queue用法 (23)5.3.map使用详解 (24)5.4.字典树建立与查找 (24)5.5.KMP匹配算法 (26)5.6.后缀数组求最长连续公共子序列长度 (27)5.7.循环字符串最小位置表示及同构判断 (30)5.8.求哈夫曼树编码长度 (32)5.9.堆排序算法 (34)5.10.线段树着色问题 (35)六、附: (38)6.1.C++最值常量 (38)6.2.类型转换 (39)6.3.String常用函数举例 (39)6.4.C++常用头文件 (40)一、图论1.1.最小生成树类prim算法1.1.1下标从1开始#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define SIZE 101#define MAXSIZE 10201int n,nline;/*n 个点,nline行关系*/int in[SIZE];struct Point{int x,y;/*编号从1开始*/int v;/*根据实际情况更改类型*/}p[MAXSIZE];/*n*(n-1)/2*/int cmp(Point a,Point b){return a.v<b.v;}int prim(){int dis,count,i,j;memset(in,0,sizeof(in));in[p[1].x]=in[p[1].y]=1;dis=p[1].v;count=n-1;while(count--){/*做n-1次*/for(j=2;j<nline;j++){if((in[p[j].x]&&!in[p[j].y])||(!in[p[j].x]&&in[p[j].y])){in[p[j].x]=1;in[p[j].y]=1;dis+=p[j].v;break;}}}return dis;}int main(){int x,y,v,i;while(scanf("%d",&n)&&n){if(n==1){/*有可能输入的为1个点*/printf("0\n");continue;}nline=n*(n-1)/2+1;for(i=1;i<nline;i++){scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].v);}sort(p+1,p+nline,cmp);printf("%d\n",prim());}return 0;}1.1.2下标从0开始#include<iostream>#include<cstdio>#include<algorithm>using namespace std;#define SIZE 101#define MAXSIZE 10201int n,nline;/*n 个点,nline行关系*/int in[SIZE];struct Point{int x,y;/*编号从1开始*/int v;/*根据实际情况更改类型*/}p[MAXSIZE];/*n*(n-1)/2*/int cmp(Point a,Point b){return a.v<b.v;}int prim(){int dis,count,i,j;memset(in,0,sizeof(in));in[p[0].x]=in[p[0].y]=1;dis=p[0].v;count=n-1;while(count--){/*做n-1次*/for(j=1;j<nline;j++){if((in[p[j].x]&&!in[p[j].y])||(!in[p[j].x]&&in[p[j].y])){in[p[j].x]=1;in[p[j].y]=1;dis+=p[j].v;break;}}}return dis;}int main(){int x,y,v,i;while(scanf("%d",&n)&&n){if(n==1){/*有可能输入的为1个点*/printf("0\n");continue;}nline=n*(n-1)/2;for(i=0;i<nline;i++){scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].v);}sort(p,p+nline,cmp);printf("%d\n",prim());}return 0;}1.2.拓扑排序#include<iostream>#include<cstdio>#include<cstring>#define M 501using namespace std;int map[M][M],degree[M];int ne;/*个数*/void topo(){int i,j,k;for(i=0;i<ne;i++){j=1;while(j<=ne&°ree[j])j++;//直到一个度为零的顶点,这里不检查有多个度为零的情况//if(j>ne){break;}不是拓扑结构if(i)printf(" ");printf("%d",j);degree[j]=-1;for(k=1;k<=ne;k++){degree[k]-=map[j][k];}}printf("\n");}int main(){int a,b,i,j,nline;/*nline行*/while(scanf("%d%d",&ne,&nline)!=EOF){memset(map,0,sizeof(map));memset(degree,0,sizeof(degree));while(nline--){scanf("%d%d",&a,&b);map[a][b]=1;/*a to b*/}for(i=1;i<=ne;i++){for(j=1;j<=ne;j++){if(map[i][j])degree[j]++;}}topo();/*拓扑*/}return 0;}1.3.最短源路径Folyd实现#include<iostream>#include<cstdio>#include<cstring>#define M 201using namespace std;int n,map[M][M],start,end;void folyd(){int i,j,k;for(i=0;i<n;i++){for(j=0;j<n;j++){for(k=0;k<n;k++){if(map[j][i]==-1||map[i][k]==-1)continue;if(map[j][k]==-1||map[j][i]+map[i][k]<map[j][k]){map[j][k]=map[j][i]+map[i][k];}}}}}int main(){int nline,i,j,a,b,v;while(scanf("%d%d",&n,&nline)!=EOF){memset(map,-1,sizeof(map));for(i=0;i<n;i++){map[i][i]=0;}for(i=0;i<nline;i++){scanf("%d%d%d",&a,&b,&v);/*编号从0开始*/if(map[a][b]==-1||map[a][b]>v){//一个点到另一个有多条路map[b][a]=map[a][b]=v;}}scanf("%d%d",&start,&end);folyd();if(map[start][end]!=-1){printf("%d\n",map[start][end]);}else printf("-1\n");}return 0;}1.4.关键路径实现算法#include<iostream>#include<cstdio>#include<cstring>#define M 501using namespace std;int map[M][M],degree[M],dp[M];int ne;/*个数*/int topoplus(){int i,j,k,maxnum;for(i=0;i<ne;i++){j=1;while(j<=ne&°ree[j])j++;//直到一个度为零的顶点,这里不检查有多个度为零的情况//if(j>ne){break;}不是拓扑结构degree[j]=-1;for(k=1;k<=ne;k++){if(map[j][k]){if(map[j][k]+dp[j]>dp[k]){dp[k]=map[j][k]+dp[j];}degree[k]--;}}}for(i=0;i<=ne;i++){if(dp[i]>maxnum){maxnum=dp[i];}}return maxnum;}int main(){int a,b,v,i,j,nline;/*nline行*/while(scanf("%d%d",&ne,&nline)!=EOF){ memset(map,0,sizeof(map));memset(degree,0,sizeof(degree));memset(dp,0,sizeof(dp));while(nline--){scanf("%d%d%d",&a,&b,&v);map[a][b]=v;/*a to b,v>0*/}for(i=1;i<=ne;i++){for(j=1;j<=ne;j++){if(map[i][j])degree[j]++;}}printf("%d\n",topoplus());/*拓扑改进*/ }return 0;}1.5.二分图最大匹配的匈牙利算法#include<iostream>#include<cstdio>#define N 301using namespace std;int isuse[N]; //记录y中节点是否使用int lk[N]; //记录当前与y节点相连的x的节点int mat[N][N];//记录连接x和y的边,如果i和j之间有边则为1,否则为0 int gn,gm; //二分图中x和y中点的数目int can(int t){int i;for(i=1;i<=gm;i++){//下标从1开始if(isuse[i]==0 && mat[t][i]){isuse[i]=1;if(lk[i]==-1 || can(lk[i])){lk[i]=t;return 1;}}}return 0;}int MaxMatch(){int i,num=0;memset(lk,-1,sizeof(lk));for(i=1;i<=gn;i++){memset(isuse,0,sizeof(isuse));if(can(i))num++;}return num;}int main(){int t,i,j,k,tmp;scanf("%d",&t);while(t--){scanf("%d%d",&gn,&gm);memset(mat,0,sizeof(mat));//主要得到mat这个数组for(i=1;i<=gn;i++){scanf("%d",&k);for(j=1;j<=k;j++){scanf("%d",&tmp);mat[i][tmp]=1;//注意从1开始}}if(MaxMatch()==gn){printf("YES\n");}else printf("NO\n");}return 0;}/*In:23 33 1 2 32 1 21 13 32 1 32 1 31 1Out:YESNO*/1.6.并查集#include<iostream>#include<cstdio>using namespace std;const int N=1010;int pre[N];void Merge(int x,int y){int i,t,rx=x,ry=y;while(pre[rx]!=-1)//搜索x的树根 rx=pre[rx];while(pre[ry]!=-1)//搜索y的树根 ry=pre[ry];i=x;//压缩xwhile(pre[i]!=-1){t=pre[i];pre[i]=rx;i=t;}i=y;//压缩ywhile(pre[i]!=-1){t=pre[i];pre[i]=rx;i=t;}if(ry!=rx)//合并pre[ry]=rx;return;}int main(){int x,y,i,ans,n,m;while(scanf("%d",&n)&&n){scanf("%d",&m);memset(pre,-1,sizeof(pre));for(i=0;i<m;i++){//x与y连通scanf("%d %d",&x,&y);Merge(x,y);}ans=0;for(i=1;i<=n;i++)if(pre[i]==-1)ans++;printf("%d\n",ans-1);}}/*/showproblem.php?pid=1232 in:4 21 34 3999 0out:1998*/二、动规2.1.求最长子序列#include<iostream>#include<cstdio>#define M 1001using namespace std;char a[M],b[M];int dp[M+1][M+1],lena,lenb;void init(){int i,j;for(i=0;i<=lena;i++){for(j=0;j<=lenb;j++){dp[i][j]=0;}}}int cmax(int x,int y){return x>y?x:y;}int main(){int i,j,len;while(scanf("%s",a)!=EOF){scanf("%s",b);init();//下面这步很重要,否则会超时lena=strlen(a);lenb=strlen(b);for(i=0;i<lena;i++){for(j=0;j<lenb;j++){if(a[i]==b[j]){dp[i+1][j+1]=dp[i][j]+1;}else{dp[i+1][j+1]=cmax(dp[i][j+1],dp[i+1][j]);}}}//子序列长度printf("%d\n",dp[i][j]);/*打印出子序列*/len=1;for(i=1;i<=lena;i++){for(j=1;j<=lenb;j++){if(len==dp[i][j]){printf("%c",a[i-1]);len++;break;}}}printf("\n");}return 0;}2.2.求解最长升序列长度及子序列#include<iostream>#include<cstdio>#define M 1001using namespace std;int a[M],dp[M];void init(int n){int i;for(i=0;i<n;i++){dp[i]=1;}}int lis(int n){int i,j,maxlen=1;//初始长度为1for(i=n-2;i>=0;i--){for(j=n-1;j>i;j--){if(a[i]<a[j]){if(dp[j]+1>dp[i]){dp[i]=dp[j]+1;}if(dp[i]>maxlen)maxlen=dp[i];}}}return maxlen;}void showlis(int n,int maxlen){int i;for(i=0;i<n;i++){if(dp[i]==maxlen){printf("%d ",a[i]);maxlen--;}}printf("\n");}int main(){int t,n,i,maxlen;scanf("%d",&t);while(t--){/*1<=n<=1000*/scanf("%d",&n);for(i=0;i<n;i++){scanf("%d",&a[i]);}init(n);maxlen=lis(n);printf("%d\n",maxlen);//显示最长升序列showlis(n,maxlen);}return 0;}2.3.完全背包问题#include<iostream>#include<cstring>#include<cstdio>using namespace std;int type[]={150,200,350};//种类int dp[10001];int max(int a,int b){return a>b?a:b;}int main(){int t,n,i,j;scanf("%d",&t);while(t--){scanf("%d",&n);memset(dp,0,sizeof(dp));for(i=0;i<3;i++){for(j=type[i];j<=n;j++){//剩余容量为j时装的东西量最大dp[j]=max(dp[j],dp[j-type[i]]+type[i]);}}printf("%d\n",n-dp[n]);}return 0;}2.4.0-1背包问题#include<iostream>#include<cstdio>#include<cstring>#define M 1002using namespace std;int val[M],wei[M],dp[M][M];int cmax(int a,int b){return a>b?a:b;}int main(){int t,n,w,i,j;scanf("%d",&t);while(t--){scanf("%d%d",&n,&w);for(i=1;i<=n;i++){scanf("%d",&val[i]);}for(i=1;i<=n;i++){scanf("%d",&wei[i]);}memset(dp,0,sizeof(dp));for(i=1;i<=n;i++){for(j=0;j<=w;j++){if(j>=wei[i])dp[i][j]=cmax(dp[i-1][j-wei[i]]+val[i],dp[i-1][j]);else dp[i][j]=dp[i-1][j];}}printf("%d\n",dp[n][w]);}return 0;}2.5.母函数DP算法求组合数2.5.1.求母函数各系数值DP#include <iostream>#define M 17#define MAX 305using namespace std;int c1[MAX],c2[MAX],add[M+1];//add[]保存M种类void init(){int i;for(i=1;i<=M;i++){add[i]=i*i;}}int solve(int n){int i,j,k;//c1[k],c2[k]表示展开式中x^k的系数memset(c1,0,sizeof(c1));memset(c2,0,sizeof(c2));c1[0]=c2[0]=1;//使用前i种币时的情况,也即母函数展开前i个多项式的乘积 for(i=1;i<=M;i++){//求新的多项式中的系数for(j=0;j<n;j++){for(k=1;j+k*add[i]<=n;k++){c2[j+k*add[i]]+=c1[j];}}for(k=0;k<=n;k++){//滚动数组c1[k]=c2[k];}}return c1[n];}int main(){int n;init();while(scanf("%d",&n)&&n){printf("%d\n",solve(n));}return 0;}2.5.2.状态继承类DP求某个和是否存在#include<cstdio>#include<iostream>#include<cstring>using namespace std;bool dp[250002];int val[101],num[101];//对应的值和数量int main(){int n,i,j,sum,k;while(scanf("%d",&n)&&n>0){sum=0;for(i=0;i<n;i++){scanf("%d%d",&val[i],&num[i]);sum+=val[i]*num[i];}//dp中保存所有可能的组合memset(dp,0,sizeof(dp));dp[0]=1;//遍历n种物品for(i=0;i<n;i++){//对区间求for(j=sum/2;j>=0;j--){if(!dp[j]){for(k=1;k<=num[i]&&k*val[i]<=j;k++){dp[j]|=dp[j-k*val[i]];}}}}for(i=sum/2;i>=0;i--){if(dp[i]){printf("%d %d\n",sum-i,i);break;}}}return 0;}/*in:210 120 1310 120 230 1-1out:40 40*/2.6.滚动数组求回文串问题#include<cstdio>#include<iostream>#include<cstring>#define M 5001using namespace std;char str[M],rstr[M];int dp[2][M];//滚动DPint cmax(int x,int y){return x>y?x:y;}int main(){int n,i,j,s1,s2;while(scanf("%d",&n)!=EOF){scanf(" %s",str);//反转字符数组for(i=0;i<n;i++){rstr[n-i-1]=str[i];}rstr[n]='\0';memset(dp,0,sizeof(dp));for(i=0;i<n;i++){for(j=0;j<n;j++){s1=i%2;s2=(i+1)%2;if(str[i]==rstr[j]){dp[s1][j+1]=dp[s2][j]+1;}else{dp[s1][j+1]=cmax(dp[s2][j+1],dp[s1][j]);}}}printf("%d\n",n-dp[(n-1)%2][n]);}return 0;}/*/showproblem.php?pid=15135Ab3bdout:2*/三、贪心3.1.时间安排问题#include<iostream>#include<cstdio>#include<algorithm>#define M 101using namespace std;int n;struct Point{int s,e;}p[M];int cmp(Point a,Point b){if(a.s==b.s)return a.e<b.e;else return a.s<b.s;}int arrange(){int start,end,i,count=1;start=p[0].s;end=p[0].e;for(i=1;i<n;i++){if(p[i].s>=start&&p[i].e<=end){start=p[i].s;end=p[i].e;}else if(p[i].s>=end){count++;end=p[i].e;}}return count;}int main(){int i;while(scanf("%d",&n)&&n){for(i=0;i<n;i++){scanf("%d%d",&p[i].s,&p[i].e);}sort(p,p+n,cmp);printf("%d\n",arrange());}return 0;}3.2.求最大子段和#include<iostream>using namespace std;int main(){int t,n,i,a[100002];int beg,end,x,y,cursum,maxsum;cin>>t;while(t--){cin>>n;for(i=0;i<n;i++){cin>>a[i];}beg=end=1;cursum=maxsum=a[0];x=y=1;for(i=1;i<n;i++){if(a[i]+cursum<a[i]){cursum=a[i];x=i+1;}else{cursum+=a[i];}if(cursum>maxsum){maxsum=cursum;beg=x;end=i+1;}}cout<<maxsum<<" "<<beg<<" "<<end<<endl;}return 0;}/*25 6 -1 5 4 -77 0 6 -1 1 -6 7 -5out:14 1 47 1 6*/3.3.贪心求最少非递减序列数#include<iostream>#include<cstdio>#include<cstring>using namespace std;int a[1001];int main(){int n,i,j,len,count,high;while(scanf("%d",&n)!=EOF){for(i=0;i<n;i++){scanf("%d",&a[i]);}count=0;len=n;while(len){count++;high=30005;//最高值for(i=0;i<n;i++){if(a[i]&&a[i]<high){high=a[i];a[i]=0;//标记已用值len--;}}}printf("%d\n",count);}return 0;}/*in:8 389 207 155 300 299 170 158 65 out:2四、数论4.1.简单求Cnk问题#include<iostream>using namespace std;int main(){int n,k,i;double sum;while(cin>>n>>k){if(n==0&&k==0)break;if(k>n-k)k=n-k;sum=1;for(i=1;i<=k;i++){sum*=(double)(n-k+i)/i*1.000000000001;//必需要乘 }cout<<(int)sum<<endl;}return 0;}4.2.巧求阶乘位数#include<iostream>#include<cmath>using namespace std;const double pi=acos(-1.0);//NOTES:piconst double e=2.71828182845904523536028747135266249775724709369995957; int main(){long long n,tt;cin>>tt;while (tt--){cin>>n;long long ans=(long long)((double)log10(sqrt(2*pi*n))+n*log10(n/e))+1;cout<<ans<<endl;}return 0;}4.3.线性算法求素数const int MAX=10000000;//求[2,MAX]间的素数bool isprime[MAX+1];int prime[MAX];//保存素数//返回素数表元素总数int getprime(){int i,j,pnum=0;//memset(isprime,0,sizeof(isprime));for(i=2;i<=MAX;i++){if(!isprime[i])prime[pnum++]=i;for(j=0;j<pnum&&prime[j]*i<=MAX;j++){isprime[prime[j]*i]=1;if(i%prime[j]==0)break;}}return pnum;}五、其他5.1.采用位操作递归求解示例#include<iostream>#include<cstdio>using namespace std;unsigned short in[50001],ste;/*用16位的ste保存16种状态*/ unsigned short power[]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768}; int n,m,maxnum,i,j;void dfs(int s,int count){if(count>maxnum)maxnum=count;for(i=s;i<m;i++){if(!(ste&in[i])){/*如果相与为0,说明材料未被使用*/ ste=ste|in[i];dfs(i+1,count+1);ste=ste&(~in[i]);}}}int main(){int tn,t;while(scanf("%d%d",&n,&m)!=EOF){if(n==0||m==0){printf("0\n");continue;}for(i=0;i<m;i++){scanf("%d",&tn);in[i]=0;for(j=1;j<=tn;j++){scanf("%d",&t);/*材料编号降为从0开始,防止益处*/in[i]=in[i]|power[t-1];}}ste=0;maxnum=0;dfs(0,0);printf("%d\n",maxnum);}return 0;}5.2.Stack和Queue用法#include<iostream>#include<stack>#include<queue>using namespace std;int main(){stack<int> s;queue<int> q;int a[]={1,2,3,4};/*加入*/for(int i=0;i<4;i++){s.push(a[i]);q.push(a[i]);}/*读取stack*/cout<<"stack-size:"<<s.size()<<endl;for(int i=0;i<4;i++){cout<<s.top()<<" ";s.pop();}cout<<endl<<"queue-size:"<<q.size()<<endl;/*读取queue*/cout<<"front:"<<q.front()<<"back:"<<q.back()<<endl;for(int i=0;i<4;i++){cout<<q.front()<<" ";q.pop();}cout<<endl;return 0;}5.3.map使用详解#include<iostream>#include<map>#include<string>#include<iterator>using namespace std;int main(){map<string,int>m;map<string,int>::iterator p;map<string,int>::reverse_iterator q;m["bd"]=2;m["ba"]=1;m["aa"]=3;m["bd"]=4;//按从小到大遍历for(p=m.begin();p!=m.end();p++){//注意不能使用p<m.end() cout<<p->first<<" "<<p->second<<endl;}//按从大到小遍历for(q=m.rbegin();q!=m.rend();q++){cout<<q->first<<" "<<q->second<<endl;}m.erase(m.begin());cout<<m.size()<<endl;//清楚全部m.clear();cout<<m.empty()<<endl;return 0;}5.4.字典树建立与查找#include<iostream>#include<cstring>#include<cstdio>#define M 26using namespace std;int ii;//只在Tree中使用struct Tree{Tree* next[M];int val;Tree(){for(ii=0;ii<M;ii++){next[ii]=0;}val=0;}~Tree(){for(ii=0;ii<M;ii++){delete(next[ii]);}}};int main(){char word[20];int len,i,j,count;Tree* root=new Tree;Tree* p;//建立字典树过程while(gets(word)){if(strcmp(word,"")==0)break;len=strlen(word);p=root;for(i=0;i<len;i++){j=word[i]-'a';if(p->next[j]==0){p->next[j]=new Tree;}p=p->next[j];(p->val)++;}word[0]='\0';}while(scanf("%s",word)!=EOF){len=strlen(word);p=root;for(i=0;i<len;i++){j=word[i]-'a';if(p->next[j]!=0){p=p->next[j];}else break;}if(i==len)printf("%d\n",p->val);else printf("0\n");}return 0;}/*In:bananabandbeeabsoluteacmbabbandabcout:231*/5.5.KMP匹配算法#include<iostream>#include<cstdio>#include<cstring>#define M 10001using namespace std;int s[M*100],t[M],next[M];//得到next数组,下标均从1开始void getnext(int m){int i=1,j=0;next[1]=0;while(i<=m){if(j==0||t[i]==t[j]){++i;++j;next[i]=j;}else j=next[j];}}//找不到则返回-1int kmp(int n,int m){int i=0,j=1;getnext(m);while(i<=n&&j<=m){if(!j||s[i]==t[j]){++i;++j;}elsej=next[j];}if(j>m)return i-m;else return -1;}int main(){int test,m,n,i;scanf("%d",&test);while(test--){scanf("%d %d",&n,&m);//主串s,长度为nfor(i=1;i<=n;i++)scanf("%d",&s[i]);//横式串t,长度为mfor(i=1;i<=m;i++)scanf("%d",&t[i]);printf("%d\n",kmp(n,m));}return 0;}5.6.后缀数组求最长连续公共子序列长度#include<iostream>#include<cstdio>#include<algorithm>#define M 100001using namespace std;char message[M*2];/*后缀数组*/int height[M*2];int _array[2][M*2];int _rank[2][M*2];int cnt[M*2];int *array, *rank, *narray, *nrank;/*得到最长连续公共子序列长度*/int suffix(int len1,int len2,int len){int i,k;memset(cnt,0,1024);for(i=0;i<len;++i){++cnt[message[i]];}for(i=1;i<= 'z';++i){cnt[i]+=cnt[i-1];}array = _array[0];rank = _rank[0];for(i=len-1;i>=0;--i){array[--cnt[message[i]]]=i;}rank[array[0]] = 0;for(i=1;i<len;i++){rank[array[i]]=rank[array[i-1]];if(message[array[i]]!=message[array[i-1]]){ rank[array[i]]++;}}narray = _array[1];nrank = _rank[1];for(k=1;k<len&&rank[array[len-1]]<len-1;k<<=1){for(i=0;i<len;++i){cnt[rank[array[i]]]=i+1;}for(i=len-1;i>=0;--i){if(array[i] >= k){// array[i]是当前的最大值,所以array[i] - k//是其相同前缀中(rank相同)的最大值narray[--cnt[rank[array[i]-k]]]=array[i]-k;}}for(i=len-k;i<len;++i){//这些没有k后缀,所以他们是最后面的k个,他的位置已经比较出来narray[--cnt[rank[i]]]=i;}nrank[narray[0]] = 0;for (i=1;i<len;++i){nrank[narray[i]]=nrank[narray[i-1]];if(rank[narray[i]]!= rank[narray[i-1]] ||rank[narray[i]+k]!=rank[narray[i-1]+k]){//如果前缀的排名不同,则++;如果前缀相同,但是后缀不同,也++ nrank[narray[i]]++;}}swap(nrank, rank);swap(narray, array);}int ret=0,hei;for(i=1;i<len;++i){if(((array[i]<len1&&array[i-1]>=len1) ||(array[i]>=len1&&array[i-1]<len1))){hei = 0;while(message[array[i]+ hei]==message[array[i-1]+hei]){hei++;}ret = max(ret, hei);}}return ret;}int main(){int len,len1,len2;while(gets(message)!=NULL){len1 = strlen(message);gets(message + len1);len2 = strlen(message+len1);len = len1 + len2;printf("%d\n",suffix(len1,len2,len));}return 0;}5.7.循环字符串最小位置表示及同构判断#include<cstdio>#include<iostream>#include<cstring>#include<string>using namespace std;//返回两个字符串是否同构//len为s1或S2的长度,s1与s2等长//pos1与pos2为字符循环最小表示位置,从0开始bool CircularMatch(string s1, string s2, int len, int& pos1, int& pos2) {int p1 = 0, p2 = 0, k, t1, t2;pos1 = pos2 = -1;while (1) {k = 0;while (1) {t1 = (p1+k)%len; t2 = (p2+k)%len;if(s1[t1] > s2[t2]) {p1 = p1+k+1;if (p1 >= len) return false;break;}else if (s1[t1] < s2[t2]) {p2 = p2+k+1;if (p2 >= len) return false;break;}else k++;if (k == len) {pos1 = p1; pos2 = p2;return true;}}}}//返回字符串循环最小表示的位置,从0开始int MinCircularDenote(string s, int len) {int p1 = 0, p2 = 1, k, t1, t2;while (1) {k = 0;while (1) {t1 = (p1+k)%len; t2 = (p2+k)%len;if(s[t1] > s[t2]) {if (p1+k+1 <= p2) p1 = p2+1;else p1 = p1+k+1;if (p1 >= len) return p2;break;}else if (s[t1] < s[t2]) {if (p2+k+1 <= p1) p2 = p1+1;else p2 = p2+k+1;if (p2 >= len) return p1;break;}else k++;if (k == len)return (p1<p2 ? p1 : p2);}}}//返回字符串循环最大表示的位置,从0开始int MaxCircularDenote(string str,int len) {int p1 = 0, p2 = 1, k, t1, t2;while (1) {k = 0;while (1) {t1 = (p1+k)%len; t2 = (p2+k)%len;if(str[t1] < str[t2]) {if (p1+k+1 <= p2) p1 = p2+1; else p1 = p1+k+1;if (p1 >= len) return p2;break;}else if (str[t1] > str[t2]) {if (p2+k+1 <= p1) p2 = p1+1;else p2 = p2+k+1;if (p2 >= len) return p1;break;}else k++;if (k == len)return (p1<p2 ? p1 : p2);}}}int main(){string s1,s2;int pos1,pos2,len;while(cin>>s1>>s2){len=s1.length();cout<<MinCircularDenote(s1,len)<<endl;cout<<MaxCircularDenote(s1,len)<<endl;s1+=s1;//字符串加倍s2+=s2;cout<<CircularMatch(s1,s2,len, pos1,pos2)<<endl;cout<<pos1<<endl<<pos2<<endl;}return 0;}5.8.求哈夫曼树编码长度#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#define M 27using namespace std;char line[100001];int tree[M],tmp[M];//保存权值int cmp(int a,int b){return a>b;}//对序号为index统计长度int huffman(int n,int index){if(n==1)return 1;//一个点时返回1int i,j,count,max,len,t;for(i=0;i<n;i++){tmp[i]=tree[i];}count=max=n-1;len=0;while(count--){if(index==max||index==max-1){len++;index=max-1;}tmp[max-1]+=tmp[max];j=--max;while(j>0&&tmp[j]>tmp[j-1]){t=tmp[j];tmp[j]=tmp[j-1];tmp[j-1]=t;if(index==j){index--;}else if(index==j-1){index++;}j--;}}return len;}int main(){int i,j,len,sum,n;int ch[M];while(gets(line)!=NULL){if(strcmp(line,"END")==0)break;len=strlen(line);memset(ch,0,sizeof(ch));for(i=0;i<len;i++){if(line[i]=='_'){ch[0]++;}else ch[line[i]-'A'+1]++;}//权值压缩到tree[]数组中for(j=0,i=0;i<M;i++){if(ch[i]){tree[j++]=ch[i];}}n=j;sort(tree,tree+n,cmp);for(sum=0,i=0;i<n;i++){sum+=tree[i]*huffman(n,i);}printf("%d %d %.1lf\n",len*8,sum,len*8.0/(sum*1.0));}return 0;}/*/showproblem.php?pid=1053in:AAAAABCDTHE_CAT_IN_THE_HATENDout:64 13 4.9144 51 2.8*/5.9.堆排序算法#include<cstdio>#include<cstdlib>using namespace std;void adjust(int a[],int s,int len){int t,i;t=a[s];for(i=s*2;i<len;i*=2){if(i<(len-1)&&a[i]<a[i+1])i++;if(t>=a[i])break;a[s]=a[i];s=i;}a[s]=t;}void sort(int a[],int len){int i,t;for(i=(len-1)/2;i>=0;i--){adjust(a,i,len);}for(i=len-1;i>1;i--){t=a[i];a[i]=a[0];a[0]=t;adjust(a,0,i-1);}if(a[0]>a[1]){t=a[0];a[0]=a[1];a[1]=t;}}int main(){int a[1000],i,n;scanf("%d",&n);//for(i=0;i<n;i++)// scanf("%d",a+i);for(i=0;i<n;i++)a[i]=rand()%10000;sort(a,n);for(i=0;i<n;i++)printf("%d ",a[i]);printf("\n");return 0;}//2 38 4 99 10 2 22 1 -43 22 33 91 78 335.10.线段树着色问题#include <iostream>#define N 8003#define NoCol -1#define MulCol -2using namespace std;struct SegTree{int l,r,c;}st[N*4];//一般大小开成节点数的4倍,不需要担心空间问题int seg[N],col[N];int n,sat,end;//创建线段树void segTreeCre(int l,int r,int i=1){int mid;st[i].l=l;st[i].r=r;st[i].c=NoCol;if(l==r){return;}mid=(l+r)/2;。
东京大学ACM模板
14 15 16 17 18 19 20 21 22 23 24 25
ቤተ መጻሕፍቲ ባይዱ
int p = Integer.highestOneBit(vs.length - 1); for (int q = p; q > 0; q >>= 1, p |= q) { if (p >= vs.length || k < vs[p]) p ^= q; else k -= vs[p]; }
University of Tokyo 2.3 1 class Intervals { 2 TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>(); 3 Intervals() { 4 5 6 7 8 9 10 11 12 13 14 15 16 } 2.4 Treap 1 class T { 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 final int key, val; final double p; final T left, right; T(int key, int val, double p, T left, T right) { this.key = key; this.val = val; this.p = p; this.left = left; this.right = right; } T change(T left, T right) { return new T(key, val, p, left, right); } T normal() { if (left != null && left.p < p && (right == null || left.p < right.p)) { return left.change(left.left, change(left.right, right)); } else if (right != null && right.p < p) { return right.change(change(left, right.left), right.right); } return this; } map.put(Integer.MIN_VALUE, -1); map.put(Integer.MAX_VALUE, -1); } void paint(int s, int t, int c) { int p = get(t); map.subMap(s, t).clear(); map.put(s, c); map.put(t, p); } int get(int k) { return map.floorEntry(k).getValue(); }
ACM赛前准备——模板(排版篇)
ACM赛前准备 ——模板(排版篇)
ACM赛前准备——模板(排版篇)
更新
2018-01-31 添加中文支持
前言
一个好的模板抵的过一个漂亮的志愿者。本文旨在方便广大ACMer赛前整理代码,把繁琐的排版工作交给工具完成,更专 注于模板本身的内容。 再次强调:本文只谈排版,本文只谈排版,本文只谈排版。
பைடு நூலகம்Tex文件内容
照着抄就行了,不需要知道tex语法,里面已写好注释,增加模板只需要在tex中加个section就行。 实例:
1. % \twocolumn % 是否需要分栏显示 2. \newpage %另起一页 3. \section{String} %一级标题 4. \subsection{KMP} %二级标题 5. \inputminted[breaklines]{c++}{string/} %导入模板文件 6. \subsection{Suffix Automaton} 7. \inputminted[breaklines]{c++}{string/}
编译
1. xelatex -shell-escape ply-template.tex
相应目录下即可生成pdf文件
总结
用tex来创建ACM模板非常容易,只需要在tex文件中写好模板结构,把模板放在相应文件夹即可,相比较word,省去了大 量复制粘贴和排版的困难,并且代码和排版分离也使得模板的修改更为容易。
效果演示
封面
目录页
模板页(不分栏)
模板页(分栏)
结果文件
快速使用
1. git clone https:///palayutm/ply-template 2. cd ply-template 3. xelatex -shell-escape ply-template.tex
算法竞赛 分数模板
算法竞赛分数模板English answer:Competitive programming scoring templates are used to evaluate the performance of participants in competitive programming competitions. They typically assign pointsbased on various factors such as the number of problems solved, the time taken to solve them, and the number of incorrect submissions. The scoring scheme can vary depending on the competition, but some common templates include:ACM Scoring: Points are awarded for each problem solved, with bonuses for solving problems quickly.Incorrect submissions incur penalties.IOI Scoring: Points are awarded for each problem solved, with partial credit for partially correct solutions. Time taken is not considered.Waterloo Scoring: Points are awarded for each problem solved, with bonuses for solving problems quickly.Incorrect submissions do not incur penalties, but they consume the contestant's time.TopCoder Scoring: Points are awarded for each problem solved, with bonuses for solving problems quickly. Contestants can submit multiple solutions for a problem, but only the highest-scoring solution will count.Competitive programming scoring templates are designed to reward problem-solving skills, efficiency, and accuracy. They encourage participants to find optimal solutions to problems and to minimize the time taken to solve them.Here is a more detailed explanation of each scoring template:ACM Scoring: This scoring template is used in the ACM International Collegiate Programming Contest (ICPC). Points are awarded as follows:+900 points for solving a problem within the first 60 minutes.+600 points for solving a problem after 60 minutes but before 120 minutes.+300 points for solving a problem after 120 minutes.-20 points for an incorrect submission.IOI Scoring: This scoring template is used in the International Olympiad in Informatics (IOI). Points are awarded as follows:+100 points for solving a problem.+50 points for a partially correct solution.0 points for an incorrect submission.Waterloo Scoring: This scoring template is used in theWaterloo Collegiate Programming Contest (WCPC). Points are awarded as follows:+100 points for solving a problem within the first 60 minutes.+75 points for solving a problem after 60 minutes but before 120 minutes.+50 points for solving a problem after 120 minutes.No penalty for incorrect submissions.TopCoder Scoring: This scoring template is used in TopCoder competitions. Points are awarded as follows:+500 points for solving a problem.+250 points for a partially correct solution.0 points for an incorrect submission.Contest organizers may also use custom scoring templates that are tailored to the specific competition. For example, some competitions may award bonus points for solving particularly difficult problems or for submitting elegant or efficient solutions.中文回答:竞赛编程评分模板用于评估竞赛编程比赛中参与者的表现。
ACM算法竞赛模板个人总结汇总
数学 (4)最大公约数、最小公倍数 (4)最大公约数——欧几里得算法O(n) (4)Stein算法O( log(max(a,b)) ) (4)最小公倍数: (4)素数相关 (5)普通素数判断 (5)筛法求素数[1,N] (5)二次筛法求素数[L,R] (6)Miller-Rabbin素数测试方法 (7)算术基本定理的定义和性质: (8)同余方程[组] 乘法模逆元中国剩余定理 (9)扩展欧几里得,求一组解x,y,使得gcd(a,b) = d = a * x + b * y (9)扩展欧几里得,求所有解x,y,使得c = a * x + b * y (10)扩展欧几里得,求a关于n的逆元a^-1,使得a * a^-1 ≡ 1(mod n) (10)扩展欧几里得,求解x,满足同余方程组x ≡ Ri(mod Ai) (10)扩展欧几里得,求解x,满足高次同余方程A^x ≡ B(mod C) (11)中国剩余定理: (13)中国剩余定理最小非负数解的算法: (14)求解a*x + b*y = c的其中一组解,使得|x| + |y|尽可能小,若相等,则a|x| + b|y|尽可能小。
(15)整数快速幂 (16)矩阵快速幂 (16)整数分解 (18)试除法整数分解 (18)筛法整数分解 (18)PollardRho大整数分解 (19)欧拉函数 (22)直接欧拉函数 (22)递推快速求欧拉函数 (23)容斥原理 (23)母函数 (24)普通母函数 (24)指数型母函数 (25)其他相关 (27)九余数定理:一个数N各位数字的和,对9取余等于这个数对9取余 (27)给你一个奇数N,求1~N的奇数平方和: S = N*(N+1)*(N+2)/6 (27)约瑟夫问题:有N个人,编号为1~N,按顺时针围成一个圈,每数k个人,就将这个人从圈中消除,问:最终只留下一个人的编号。
(27)给你整数x和y的和以及x和y的积,是否能找到满足这两个式子的整数x和整数y。
ACM模板(Java)
ACM模板(Java)模板TrieHIHOCODER1014static final int N = (int)1e5+10;static final int SIGMA=(int)27;static int ch[][]=new int[N*10][SIGMA],sz;static int var[]=new int[N*10];static void insert(String x){int u=0;for(int i=0;i<x.length();i++){int c=x.charAt(i)-'a';if(ch[u][c]==0){for(int t=0;t<SIGMA;t++){ch[sz][t]=0;}ch[u][c]=sz;var[sz++]=0;}u=ch[u][c];var[u]++;}}static int search(String x){int u=0;for(int i=0;i<x.length();i++){int c=x.charAt(i)-'a';if(ch[u][c]!=0) u=ch[u][c];else return 0;}return var[u];}static void clear() {sz=1;var[0]=0;for(int i=0;i<SIGMA;i++) {ch[0][i]=0;}}KMPHIHOCODER 1015写法1static void getFail(char[] b) {int m=b.length,j=0;f[0]=f[1]=0;for(int i=1;i<m;i++) {while(j>0&&b[j]!=b[i]) j=f[j];if(b[j]==b[i]) j++;f[i+1]=j;}}static int kmp_count(char[] a,char[] b) {int n=a.length,m=b.length;int j=0,res=0;for(int i=0;i<n;i++) {while(j>0&&b[j]!=a[i]) j=f[j];if(b[j]==a[i]) j++;if(j==m) {j=0;res++;}}return res;写法2static void getFail(char[] b,int m) {int j=0;f[1]=0;for(int i=2;i<=m;i++) {while(j>0&&b[j+1]!=b[i]) j=f[j];if(b[j+1]==b[i]) j++;f[i]=j;}}static int kmp_count(char[] a,char[] b,int n,int m) { int j=0,res=0;for(int i=1;i<=n;i++) {while(j>0&&b[j+1]!=a[i]) j=f[j];if(b[j+1]==a[i]) j++;if(j==m) {j=0;res++;}}return res;}ManacherHIHOCODER1016static final int N=(int)1e6+10;static char a[]=new char[N],str[]=new char[2*N+5]; static int p[]=new int[2*N+5],len1,len2;static void Init(){len1=a.length;str[0]='(';str[1]='#';for(int i=0;i<len1;i++){str[i*2+2]=a[i];str[i*2+3]='#';}len2=len1*2+2;str[len2]=')';}static int Manacher(){for(int i=0;i<len2;i++) p[i]=0;int id=0,mx=0,ans=0;for(int i=1;i<len2;i++){if(mx>i) p[i]=Math.min(mx-i,p[2*id-i]);else p[i]=1;for(;str[i+p[i]]==str[i-p[i]];p[i]++);if(p[i]+i>mx){mx=p[i]+i;id=i;}if(p[i]-1>ans) ans=p[i]-1;}return ans;}Tire图HIHOCODER 1036static int sz;static final int N=1000005;static class Node{Node(){post = 0;for(int i = 0; i < 26; i++)next[i] = 0;end = false;int post;int next[]=new int[26];boolean end;};static Node nodes[]=new Node[N];//将str添加到trie图中static void insert(String str){int cur=0;for(int i=0;i<str.length();i++){if(nodes[cur].next[str.charAt(i)-'a'] == 0)nodes[cur].next[str.charAt(i)-'a'] = ++sz;cur = nodes[cur].next[str.charAt(i)-'a'];}nodes[cur].end = true;}//为trie图中的每个点添加它指向的后缀点位置static void addPost(){LinkedList<Integer> que = new LinkedList<Integer>();que.push(0);int cur;while(!que.isEmpty()){cur=que.pop();for(int i=0;i<26;i++){if(nodes[cur].next[i]!=0){que.push(nodes[cur].next[i]);if(cur != 0)//不是根结点,需要设置当前点的⼦节点的后缀=⽗结点的后缀经过i到达的点 nodes[nodes[cur].next[i]].post = nodes[nodes[cur].post].next[i];}else //nodes[current].next[i] == -1当前点经过i没有可达的nodes[cur].next[i] = nodes[nodes[cur].post].next[i];}}}//查找strstatic boolean search(String str){int cur = 0;for(int i=0;i<str.length();i++){if(nodes[nodes[cur].next[str.charAt(i)-'a']].end)return true;cur = nodes[cur].next[str.charAt(i)-'a'];}return false;}static void Init() {sz=0;for(int i=0;i<=1000000;i++) {nodes[i]=new Node();}}。
字典树模板acm竞赛可用
字典书模板今天AC了两题trie tree的题目,感觉trie的性质真的是相当的好,而且实现比较简单。
它使在字符串集合中查找某个字符串的操作的复杂度降到最大只需O(n),其中n为字符串的长度。
trie是典型的将时间置换为空间的算法,好在ACM中一般对空间的要求很宽松。
trie的原理是利用字符串集合中字符串的公共前缀来降低时间开销以达到提高效率的目的。
它具有以下性质:1,根结点不包含任何字符信息;2,如果字符的种数为n,则每个结点的出度为n(这样必然会导致浪费很多空间,这也是trie的缺点,我还没有想到好点的办法避免);3,查找,插入复杂度为O(n),n为字符串长度。
举一个例子,给50000个由小写字母构成的长度不超过10的单词,然后问某个公共前缀是否出现过。
如果我们直接从字符串集中从头往后搜,看给定的字符串是否为字符串集中某个字符串的前缀,那样复杂度为O(50000^2),这样显然会TLE。
又或是我们对于字符串集中的每个字符串,我们用MAP存下它所有的前缀。
然后询问时可以直接给出结果。
这样复杂度为O(50000*len),最坏情况下len为字符串最长字符串的长度。
而且这没有算建立MAP存储的时间,也没有算用MAP查询的时间,实际效率会更低。
但如果我们用trie的话,当查询如字符串abcd是否为某字符串的前缀时,显然以b,c,d....等不是以a开头的字符串就不用查找了。
实际查询复杂度只有O(len),建立trie的复杂度为O(50000).这是完全可以接受的。
如给定字符串集合abcd,abd,cdd,efg,hij,hi六个字符串建立的trie tree如下图所示:查找一个字符串时,我们只需从根结点按字符串中字符出现顺序依次往下走。
如果到最后字符串结束时,对应的结点标记为红色,则该字符串存在;否则不存在。
插入时也只需从根结点往下遍历,碰到已存在的字符结点就往下遍历,否则,建立新结点;最后标记最后一个字符的结点为红色即可。
acm模板byliyang
【含负数】 int getint(){ int t=0,flag=1; char c=getchar(); while(c<'0'||c>'9'||c=='-'){ if(c=='-') flag=-1 ; c=getchar(); } while(c>='0'&&c<='9'){ t=t*10+c-'0'; c=getchar(); } return t*flag; }
【常用头文件】 #include <iostream> #include <stdio.h> #include <math.h> #include <algorithm> #include <string> #include <string.h> #include <stdlib.h> #include <map> #include <queue> #include <stack> #include <vector> #include <limits.h> //INT_MAX 在此
ACM比赛模板
ACM比赛模板目录1.最小生成树 (4)2.最短路算法 (9)3.素数打表 (17)4.最大匹配 (18)5.线段树(敌兵布阵) (23)6.线段树(逆序树) (26)7.树形dp (29)8.树状数组(段跟新) (33)9.Kmp模板 (37)10.线段树(点跟新) (46)11.强连通 (50)12.最小割 (55)13.单源最短路(spfa) (62)14.三分查找 (66)15.字典树(统计难题) (68)16.最大流入门题1273 (72)17.状态压缩 (75)18.匈牙利(HDU 2063)(最大匹配) (77)19.凸包(HDU1348) (79)20.树状数组(HDU1166) (82)21.强连通 (84)22.前向星 (87)23.矩阵 (92)24.并查集 (94)25. SORT (95)26. STL (97)27. LCA (HDU 2874) (101)28. 01背包 (104)29. 状态压缩代码: (107)30. 快速幂 (111)31.矩阵快速幂 (113)32.GCD & LCM (116)11834. /** 大数(高精度)求幂**/12335. /** 大数除法与求余**/ (127)36. /** 大数阶乘**/ (131)37. /** 大数乘法**/ (133)38. /** 大数累加**/ (136)1.最小生成树要连通n个城市需要n-1条边线路。
可以把边上的权值解释为线路的造价。
则最小生成树表示使其造价最小的生成树。
prim算法(矩阵形式):#define inf 0x3f3f3f3fint prim(int n,int sta)//n表示有n个顶点,sta表从sta这个顶点出发生成最小生成树{int mark[M],dis[M];int i,sum = 0; //sum是总的最小生成树边权值for (i = 0;i < n;i ++) //初始化dis[i] 表从顶点sta到点i的权值 {dis[i] = mat[sta][i];mark[i] = 0;}mark[sta] = 1; //sta 这个顶点加入最小生成树中 for (i = 1;i < n;i ++) //循环n-1次,每次找出一条最小权值的边 n个点的图{ //只有n-1条边int min = inf; //inf 表无穷大for (j = 0;j < n;j ++)//找出当前未在最小生成树中边权最小的顶点if (!mark[j] && dis[j] < min)min = dis[j],flag = j;mark[flag] = 1; //把该顶点加入最小生成树中sum += dis[flag]; //sum加上其边权值for (j = 0;j < n;j ++) //以falg为起点更新到各点是最小权值if (dis[j] > mat[flag][j])dis[j] = mat[flag][j];}return sum; //返回边权总和}prim算法(边表形式):struct Edge//frm为起点,to为终点,w为边权,nxt指向下一个顶点{// int frm;int to,w,nxt;}edge[M];int vis[M],head[M],dis[M];void addedge (int cu,int cv,int cw)//生成边的函数{//edge[e].frm = cu;edge[e].to = cv;edge[e].w = cw;edge[e].nxt = head[cu];head[cu] = e ++;//edge[e].frm = cv;edge[e].to = cu;edge[e].w = cw;edge[e].nxt = head[cv];head[cv] = e ++;}int prim(int n,int sta) //n为顶点数量,sta为起点{int sum = 0;memset(dis,0x3f,sizeof(dis));memset(vis,0,sizeof(vis));for (i = head[sta];i != -1;i = edge[i].nxt)//遍历与sta点相连的所有顶点 {int v = edge[i].to;dis[v] = edge[i].w;}vis[sta] = 1; //加入到最小生成树中int m = n - 1; //只生成n-1条边,所以循环n-1次while (m --){int min = inf;for (i = 0;i < n;i ++)//找出当前边权最小的边if (!vis[i]&&dis[i] < min)flag = i,min = dis[i];sum += dis[flag];vis[flag] = 1;//加入到最小生成树中for (i = head[flag];i != -1;i = edge[i].nxt) //更新与flag顶点相连的点的dis{int v = edge[i].to;if (edge[i].w < dis[v])dis[v] = edge[i].w;}}return sum; //返回边权总和}int main (){e = 0; //记得初始化memset (head,-1,sizeof(head));scanf ("%d %d %d",&a,&b,&w);addedge(a,b,w);..........prim(n,sta);return 0;}Kruskal算法:struct Edge{int v1,v2,w;}edge[M],tree[M]; //w为v1顶点到v2顶点的边权/ *int Find (int parent[],int u)//第1种写法{int tmp = u;while (paren[tmp] != -1)tmp = parent[tmp];return tmp;}*/int Find (int u) //第2种写法{if (u != parent[u])parent[u] = Find(paren[u]);return parent[u];}bool cmp (Edge a,Edge b){return a.w < b.w;}int Kruskal()//parent[]表示集合{int parent[M];int i,j,sum,vf1,vf2;sort(edge,edge+E,cmp);// memset (parent,-1,sizeof(parent));//对应第1种并查集的初始化for (i = 0;i < n;i ++) //对应第2种并查集的初始化parent[i] = i;sum = i = j = 0;while (i < E && j < N - 1)//生成的边数为N-1{vf1 = Find(parent,edge[i].v1); //找这两个点的祖先vf2 = Find(parent,edge[i].v2);if (vf1 != vf2) //若两个点的祖先不同,说明不在同一集合{parent[vf2] = vf1;//把vf2点加到vf1点的集合中tree[j++] = edge[i];//把边加到tree[]数组中,这句题目没要求可忽略之sum += edge[i].w; //sum 加上其边权}i ++;}return sum;}最小生成树 -- Kruskal算法:运用数组存点与边的权值#include <stdio.h>#include <stdlib.h>#include <algorithm>#define N 150using namespace std;int m,n,u[N],v[N],w[N],p[N],r[N];int cmp(const int i,const int j) {return w[i]<w[j];} int find(int x) {return p[x]==x?x:p[x]=find(p[x]);}int kruskal(){int cou=0,x,y,i,ans=0;for(i=0;i<n;i++) p[i]=i;for(i=0;i<m;i++) r[i]=i;sort(r,r+m,cmp);for(i=0;i<m;i++){int e=r[i];x=find(u[e]);y=find(v[e]);if(x!=y) {ans += w[e];p[x]=y;cou++;}}if(cou<n-1) ans=0;return ans;}int main(){int i,ans;while(scanf("%d%d",&m,&n)!=EOF&&m){for(i=0;i<m;i++){scanf("%d%d%d",&u[i],&v[i],&w[i]);}ans=kruskal();if(ans) printf("%d\n",ans);else printf("?\n",ans);}return 0;}2.最短路算法①DIJKC++代码1.#define inf 0x3fffffff2.#define M 1053.4.int dist[M], map[M][M], n;5.bool mark[M];6.7.void init ()8.{9. int i, j;10. for (i = 1; i <= n; i++) //i==j的时候也可以初始化为0,只是有时候不合适11. for (j = 1; j <= n; j++)12. map[i][j] = inf;13.}14.15.void dijk (int u)16.{17. int i, j, mins, v;18. for (i = 1; i <= n; i++)19. {20. dist[i] = map[u][i];21. mark[i] = false;22. }23. mark[u] = true;24. dist[u] = 0; //既然上面的map当i==j时不是0,就要这句25. while (1)26. {27. mins = inf;28. for (j = 1; j <= n; j++)29. if (!mark[j] && dist[j] < mins)30. mins = dist[j], v = j;31. if (mins == inf)32. break;33. mark[v] = true;34. for (j = 1; j <= n; j++)35. if (!mark[j] && dist[v] + map[v][j] < dist[j])36. dist[j] = dist[v] + map[v][j];37. }38.}②Floyd1.#define inf 0x3fffffff //注意,太大会溢出2.#define M //最大点数3.int n, dist[M][M]; //n:实际点数4.5.void init () //有时候需要初始化6.{7. int i, j;8. for (i = 1; i <= n; i++)9. for (j = i + 1; j <= n; j++)10. dist[i][j] = dist[j][i] = inf;11.}12.13.void floyd ()14.{15. int i, j, k;16. for (k = 1; k <= n; k++)17. for (i = 1; i <= n; i++)18. for (j = 1; j <= n; j++) //有的题目会溢出就要自己变通了19. if (dist[i][k] + dist[k][j] < dist[i][j])20. dist[i][j] = dist[i][k] + dist[k][j];21.}③vector后插的SPFAC++代码1.#define inf 0x3fffffff2.#define M 105 //最大点数3.struct son{4. int v, w;5.};6.vector<son> g[M];7.bool inq[M]; //入队列标记8.int dist[M], n; //n:实际点数9.10.void init ()11.{12. for (int i = 1; i <= n; i++)13. g[i].clear();14.}15.16.void spfa (int u)17.{18. int i, v, w;19. for (i = 1; i <= n; i++)20. {21. dist[i] = inf;22. inq[i] = false;23. }24. queue<int> q;25. q.push (u);26. inq[u] = true;27. dist[u] = 0;28. while (!q.empty())29. {30. u = q.front();31. q.pop();32. inq[u] = false;33. for (i = 0; i < g[u].size(); i++)34. {35. v = g[u][i].v;36. w = g[u][i].w;37. if (dist[u] + w < dist[v])38. {39. dist[v] = dist[u] + w;40. if (!inq[v])41. {42. q.push (v);43. inq[v] = true;44. }45. }46. }47. }48.}④模拟前插的SPFA(多数情况下比③快,数据较为复杂就会看出来) C++代码1.#define inf 0x3fffffff2.#define M 1005 //最大点数3.4.struct edge{5. int v, w, next;6.}e[10005]; //估计好有多少条边7.8.int pre[M], cnt, dist[M], n;9.bool inq[M];10.//注意初始化11.void init ()12.{13. cnt = 0;14. memset (pre, -1, sizeof(pre));15.}16.//注意双向加边17.void addedge (int u, int v, int w) //加边函数,慢慢模拟就会明白的18.{19. e[cnt].v = v;20. e[cnt].w = w;21. e[cnt].next = pre[u]; //接替已有边22. pre[u] = cnt++; //自己前插成为u 派生的第一条边23.}24.25.void spfa (int u)26.{27. int v, w, i;28. for (i = 1; i <= n; i++) //对于从1到n的编号29. dist[i] = inf, inq[i] = false;30. dist[u] = 0;31. queue<int> q;32. q.push (u);33. inq[u] = true;34. while (!q.empty())35. {36. u = q.front();37. q.pop();38. inq[u] = false;39. for (i = pre[u]; i != -1; i = e[i].next)40. {41. w = e[i].w;42. v = e[i].v;43. if (dist[u] + w < dist[v])44. {45. dist[v] = dist[u] + w;46. if (!inq[v])47. {48. q.push (v);49. inq[v] = true;50. }51. }52. }53. }54.}3.素数打表#include<iostream>#include<cstring>#include<cmath>#define MAXN 5000using namespace std;int prime[MAXN];void print_prime(){int n = (int) sqrt(MAXN); for(int i = 2; i < n; i++) {if( !prime[i] ){for(int j = i*i; j < MAXN; j += i)prime[j] = 1;prime[++prime[0]] = i;}}for(int i = n; i < MAXN; i++)if(!prime[i])prime[++prime[0]] = i;}int main(){FILE *out;out = fopen("out.txt","w");print_prime();for(int i = 1; i <= prime[0]; i++)fprintf(out, "%d,", prime[i]); return 0;}4.最大匹配#include<stdio.h>#include<string.h>#define MAX 505bool used[MAX];bool match[MAX][MAX];int boys[MAX],girls[MAX];int k, n;void init(){memset(girls, -1, sizeof(girls));memset(boys, -1, sizeof(boys));memset(match, false, sizeof(match)); }bool can(int t){int i;for(i = 0; i < n; i ++){if(!used[i] && match[t][i]){u sed[i] = true;if(girls[i] = = -1 || can(girls[i])) {boys[t] = i;girls[i] = t;return true;}}}return false;}int main(){int tmpa, tmpb, i, res, t;while(scanf("%d", &n) != EOF){init();for(i = 0; i < n; ++i){scanf("%d: (%d)", &tmpa, &k);while(k- -){scanf("%d", &tmpb);match[tmpa][tmpb] = true;res = 0;for(i = 0; i < n; i++){if(boys[i] == -1){memset(used, false, sizeof(used));if(can(i)) res ++;}}}}printf("%d\n", n - res/2);}return 0;}5.线段树(敌兵布阵)#include<stdio.h>#include<string.h>int a[50005],n;void update(int x,int c){int i;for(i=x;i<=n;i+=(i&(-i)))a[i]+=c;}int s(int x){int i;int sum=0;for(i=x;i>0;i-=(i&-i)){sum+=a[i];} return sum;}int main(){int t,i,c,b=1;int z,y;char sh[15];scanf("%d",&t);while(t--){memset(a,0,sizeof(a));scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&c);update(i,c);}printf("Case %d:\n",b++); while(~scanf("%s",sh)){if(sh[0]=='E')break;scanf("%d%d",&z,&y);if(sh[0]=='A')update(z,y);else if(sh[0]=='S')update(z,-y);else printf("%d\n",s(y)-s(z-1));}}return 0;}6.线段树(逆序树)#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int a[500005],n;int b[500005];int d[500005];void update(int x,int c){ int i;for(i=x;i<=n;i+=(i&(-i))) a[i]+=c;}int s(int x){int i;int sum=0;for(i=x;i>0;i-=(i&-i)){sum+=a[i];}return sum;}int main(){int i,j;int ans;while(scanf("%d",&n)!=EOF,n) {memset(d,0,sizeof(d));for(i=1;i<=n;i++){scanf("%d",&b[i]);b[i]=b[i]+1;d[i]=b[i];}sort(b+1,b+n+1);memset(a,0,sizeof(a));ans=0;for(i=1;i<=n;i++){update(d[i],1);printf("%d ",s(d[i]));ans+=i-s(d[i]);printf("%d ",ans);}printf("%d\n",ans);}return 0;}7.树形dp#include<stdio.h>#include<iostream>using namespace std;struct Tree{intfather,child,brother,with_max,without_max ;int MAX(){returnwith_max>=without_max?with_max:without_ma x;}void init(){father=child=brother=without_max=0;}}tree[6001];void dfs(int id)int child;child=tree[id].child;while(child){dfs(child);tree[id].with_max+=tree[child].without_ max;tree[id].without_max+=tree[child].MAX() ;child=tree[child].brother;}}int main(){int n,i;while(scanf("%d",&n)!=EOF){for(i=1;i<=n;i++){scanf("%d",&tree[i].with_max);tree[i].init();}int a,b;while(scanf("%d%d",&a,&b),a||b){tree[a].father=b;tree[a].brother=tree[b].child;tree[b].child=a;}for(i=1;i<n;i++)if(!tree[i].father){dfs(i);printf("%d\n",tree[i].MAX());break;}}return 0;}8.树状数组(段跟新)1.#include <stdio.h>2.#include <string.h>3.const int MAXN=110000;4.int n,c[MAXN];5.int lowbit(int x)6.//计算2^k7.{8. x=x&-x;9. return x;10.}11.void update(int num,int val)12.//向下查询,num是要更新的子节点,val是要修改的值13.{14. while(num>0)15. {16. c[num]+=val;17. num-=lowbit(num);18. }19.}20.int getSum(int num)21.//向上统计每个区间被染色的次数22.{23. int sum=0;24. while(num<=n)25. {26. sum+=c[num];27. num+=lowbit(num);28. }29. return sum;30.}31.int main()32.{33. int a,b;34. while(scanf("%d",&n),n)35. {36. memset(c,0,sizeof(c));37. for(int i=0;i<n;i++)38. {39. scanf("%d%d",&a,&b);40. //将b以下区间+141. update(b,1);42. //将a以下区间-143. update(a-1,-1);44. }45. for(int j=1;j<n;j++)46. {47. printf("%d ",getSum(j));48. }49. printf("%d\n",getSum(n));50. }51. return 0;52.}9.Kmp模板#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#define N 1000010int len,len1,next[N];int str[N],str1[N];void get_next(){int i=0,j=-1;next[0]=-1;while(i<=len1){if(j==-1||str1[i]==str1[j]){i++;j++;next[i]=j;}elsej=next[j];}}int kmp(){int i=0,j=0;{if(j==-1||str[i]==str1[j]) {i++;j++;}else{j=next[j];}}if(j>=len1){return i-len1+1;}return 0;}int main(){int i,t,flag;scanf("%d",&t);while(t--){memset(str,0,sizeof(str));memset(str1,0,sizeof(str1));memset(next,0,sizeof(next));scanf("%d%d",&len,&len1);for(i=0;i<len;i++)scanf("%d",&str[i]);for(i=0;i<len1;i++)scanf("%d",&str1[i]);get_next();flag=kmp();// p rintf("%d\n",flag);if(flag==0)printf("-1\n");elseprintf("%d\n",flag);}return 0; }计算出字符串 str2 中含有的 str1 的个数#include<stdio.h>#include<string.h>int next[10005];char str1[10005], str2[1000005];int n, m, ans;void getNext(char *p, int *next){int j, k;next[0] = -1;j = 0;k = -1;while(j < m){if(k == -1 || p[j] == p[k]) //匹配的情况下,p[j]==p[k]{j++;k++;next[j] = k;//printf("%d **%d **%d\n",j, k, next[j]);}else//p[j]!=p[k]k = next[k];}}int KMPMatch(char *s, char *p){int i = 0, j = 0;getNext(p, next);/*for(i = 1; i < m; i++) printf("%d ", next[i]);i = 0; printf("\n");*/while(i < n){if(j == -1 || s[i] == p[j]){i++;j++;}else{j = next[j]; //消除了指针i的回溯printf("i = %d, j = %d\n", i, j), }if(j == m )ans++;//return i - m + 1;}return ans;}int main(){int T;scanf("%d",&T);while(T--){memset(str1, '\0', sizeof(str1));memset(str2, '\0', sizeof(str2));memset(next, 0, sizeof(next));ans = 0;scanf("%s", str1);scanf("%s", str2);n = strlen(str2);m = strlen(str1);printf("%d\n",KMPMatch(str2, str1));}return 0;}10.线段树(点跟新)#include<stdio.h>#include<string.h>#define N 200010struct Node{int l,r,max;}node[3*N];int score[N];int max(int a,int b){return a>b?a:b;}void Build(int left,int right,int index) {node[index].l=left;node[index].r=right;if(left==right)node[index].max=score[left];else{int mid;mid=(left+right)/2;Build(left,mid,index*2);Build(mid+1,right,index*2+1);node[index].max=max(node[2*index].max,n ode[2*index+1].max);}}void Update(int stu,int c,int index){node[index].max=max(c,node[index].max);if(node[index].l==node[index].r){return ;}if(stu<=node[2*index].r){Update(stu,c,index*2);}else{Update(stu,c,index*2+1);}}int query(int left,int right,int index) {if(left==node[index].l&&right==node[ind ex].r){return node[index].max;}if(right<=node[2*index].r){return query(left,right,index*2);}if(left>=node[2*index+1].l){return query(left,right,index*2+1);}intmid=(node[index].l+node[index].r)/2;returnmax(query(left,mid,2*index),query(mid+1,r ight,index*2+1));}int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF) {int i;for(i=1;i<=n;i++)scanf("%d",&score[i]);getchar();char c;int s,e;Build(1,n,1);for(i=0;i<m;i++){scanf("%c%d%d",&c,&s,&e);getchar();if(c=='U'){Update(s,e,1);}if(c=='Q'){printf("%d\n",query(s,e,1));}}}return 0;11.强连通# include<stdio.h># include<string.h># define N 1005# define M 2005struct node{int from,to,next;}edge1[M],edge2[M];intvisit1[N],visit2[N],head1[N],head2[N],T[N ];intin_degree[N],out_degree[N],tol1,tol2,Bcnt ,Tcnt;int val[N],v1[N],min,Belong[N];。
ACM大赛必备_常用函数整理_ACM模板
目录一、数学问题 (4)1.精度计算——大数阶乘 (4)2.精度计算——乘法(大数乘小数) (4)3.精度计算——乘法(大数乘大数) (5)4.精度计算——加法 (6)5.精度计算——减法 (7)6.任意进制转换 (8)7.最大公约数、最小公倍数 (9)8.组合序列 (10)9.快速傅立叶变换(FFT) (10)10.Ronberg 算法计算积分 (12)11.行列式计算 (14)12.求排列组合数 (15)13.求某一天星期几 (15)14.卡特兰(Catalan) 数列原理 (16)15.杨辉三角 (16)16.全排列 (17)17.匈牙利算法----最大匹配问题 (18)18.最佳匹配KM 算法 (20)二、字符串处理 (22)1.字符串替换 (22)2.字符串查找 (23)3.字符串截取 (24)4.LCS-最大公共子串长度 (24)5.LCS-最大公共子串长度 (25)6.数字转换为字符 (26)三、计算几何 (27)1.叉乘法求任意多边形面积 (27)2.求三角形面积 (27)3.两矢量间角度 (28)4.两点距离(2D、3D) (28)5.射向法判断点是否在多边形内部 (29)6.判断点是否在线段上 (30)7.判断两线段是否相交 (31)8.判断线段与直线是否相交 (32)9.点到线段最短距离 (32)10.求两直线的交点 (33)11.判断一个封闭图形是凹集还是凸集 (34)12.Graham 扫描法寻找凸包 (35)13.求两条线段的交点 (36)四、数论 (37)1.x 的二进制长度 (37)2.返回x 的二进制表示中从低到高的第i 位 (38)3.模取幂运算 (38)4.求解模线性方程 (39)5.求解模线性方程组(中国余数定理) (39)6.筛法素数产生器 (40)7.判断一个数是否素数 (41)8.求距阵最大和 (42)8.求一个数每一位相加之和 (43)10.质因数分解 (43)11.高斯消元法解线性方程组 (44)五、图论 (45)1.Prim 算法求最小生成树................................................. 45 2.Dijkstra 算法求单源最短路径.. (46)3.Bellman-ford 算法求单源最短路径 (47)4.Floyd-Warshall 算法求每对节点间最短路径 (48)5.解欧拉图 (49)六、排序/查找 (50)1.快速排序 (50)2.希尔排序 (51)3.选择法排序 (52)4.二分查找 (52)七、数据结构 (53)1.顺序队列 (53)2.顺序栈 (56)3.链表 (59)4.链栈 (63)5.二叉树 (66)八、高精度运算专题 (68)1.专题函数说明 (68)2.高精度数比较 (69)3.高精度数加法 (69)4.高精度数减法 (70)5.高精度乘10 (71)6.高精度乘单精度 (71)7.高精度乘高精度 (72)8.高精度除单精度 (72)9.高精度除高精度 (73)九、标准模板库的使用 (74)1.计算求和 (74)2.求数组中的最大值 (76)3. sort 和qsort (76)十、其他 (78)1.运行时间计算 (78)一、数学问题1.精度计算——大数阶乘语法:int result=factorial(int n);参数:n:n 的阶乘返回值:阶乘结果的位数注意:本程序直接输出n!的结果,需要返回结果请保留long a[] 需要math.h源程序:int factorial(int n){long a[10000];int i,j,l,c,m=0,w;a[0]=1;for(i=1;i<=n;i++){c=0;for(j=0;j<=m;j++){a[j]=a[j]*i+c;c=a[j]/10000;a[j]=a[j]%10000;}if(c>0) {m++;a[m]=c;}}w=m*4+log10(a[m])+1;printf("\n%ld",a[m]);for(i=m-1;i>=0;i--) printf("%4.4ld",a[i]);return w;}我也可以做到..5 / 782.精度计算——乘法(大数乘小数)语法:mult(char c[],char t[],int m);参数:c[]:被乘数,用字符串表示,位数不限t[]:结果,用字符串表示m:乘数,限定10 以内返回值:null注意:需要string.h源程序:void mult(char c[],char t[],int m){int i,l,k,flag,add=0;char s[100];l=strlen(c);for (i=0;i<l;i++)s[l-i-1]=c[i]-'0';for (i=0;i<l;i++){k=s[i]*m+add;if (k>=10) {s[i]=k%10;add=k/10;flag=1;} else{s[i]=k;flag=0;add=0;}}if (flag) {l=i+1;s[i]=add;} else l=i;for (i=0;i<l;i++)t[l-1-i]=s[i]+'0'; t[l]='\0';}3.精度计算——乘法(大数乘大数)语法:mult(char a[],char b[],char s[]);参数:a[]:被乘数,用字符串表示,位数不限b[]:乘数,用字符串表示,位数不限t[]:结果,用字符串表示返回值:null注意:空间复杂度为o(n^2)需要string.h源程序:void mult(char a[],char b[],char s[]){我也可以做到..6 / 78int i,j,k=0,alen,blen,sum=0,res[65][65]={0},flag=0; char result[65];alen=strlen(a);blen=strlen(b);for (i=0;i<alen;i++)for (j=0;j<blen;j++) res[i][j]=(a[i]-'0')*(b[j]-'0');for (i=alen-1;i>=0;i--){for (j=blen-1;j>=0;j--) sum=sum+res[i+blen-j-1][j]; result[k]=sum%10;k=k+1;sum=sum/10;}for (i=blen-2;i>=0;i--){for (j=0;j<=i;j++) sum=sum+res[i-j][j];result[k]=sum%10;k=k+1;sum=sum/10;}if (sum!=0) {result[k]=sum;k=k+1;}for (i=0;i<k;i++) result[i]+='0';for (i=k-1;i>=0;i--) s[i]=result[k-1-i];s[k]='\0';while(1){if (strlen(s)!=strlen(a)&&s[0]=='0')strcpy(s,s+1);elsebreak;}}4.精度计算——加法语法:add(char a[],char b[],char s[]);参数:a[]:被加数,用字符串表示,位数不限b[]:加数,用字符串表示,位数不限s[]:结果,用字符串表示返回值:null注意:空间复杂度为o(n^2)我也可以做到..7 / 78需要string.h源程序:void add(char a[],char b[],char back[]){int i,j,k,up,x,y,z,l;char *c;if (strlen(a)>strlen(b)) l=strlen(a)+2; else l=strlen(b)+2; c=(char *) malloc(l*sizeof(char));i=strlen(a)-1;j=strlen(b)-1;k=0;up=0;while(i>=0||j>=0){if(i<0) x='0'; else x=a[i];if(j<0) y='0'; else y=b[j];z=x-'0'+y-'0';if(up) z+=1;if(z>9) {up=1;z%=10;} else up=0;c[k++]=z+'0';i--;j--;}if(up) c[k++]='1';i=0;c[k]='\0';for(k-=1;k>=0;k--)back[i++]=c[k];back[i]='\0';}5.精度计算——减法语法:sub(char s1[],char s2[],char t[]);参数:s1[]:被减数,用字符串表示,位数不限s2[]:减数,用字符串表示,位数不限t[]:结果,用字符串表示返回值:null注意:默认s1>=s2,程序未处理负数情况需要string.h源程序:void sub(char s1[],char s2[],char t[])我也可以做到..8 / 78{int i,l2,l1,k;l2=strlen(s2);l1=strlen(s1);t[l1]='\0';l1--;for (i=l2-1;i>=0;i--,l1--){if (s1[l1]-s2[i]>=0)t[l1]=s1[l1]-s2[i]+'0';else{t[l1]=10+s1[l1]-s2[i]+'0';s1[l1-1]=s1[l1-1]-1;}}k=l1;while(s1[k]<0) {s1[k]+=10;s1[k-1]-=1;k--;}while(l1>=0) {t[l1]=s1[l1];l1--;}loop:if (t[0]=='0') {l1=strlen(s1);for (i=0;i<l1-1;i++) t[i]=t[i+1];t[l1-1]='\0';goto loop;}if (strlen(t)==0) {t[0]='0';t[1]='\0';}}6.任意进制转换语法:conversion(char s1[],char s2[],char t[]);参数:s[]:转换前的数字s2[]:转换后的数字d1:原进制数d2:需要转换到的进制数返回值:null注意:高于9 的位数用大写'A'~'Z'表示,2~16 位进制通过验证源程序:void conversion(char s[],char s2[],long d1,long d2){我也可以做到..9 / 78long i,j,t,num;char c;num=0;for (i=0;s[i]!='\0';i++){if (s[i]<='9'&&s[i]>='0') t=s[i]-'0'; else t=s[i]-'A'+10;num=num*d1+t;}i=0;while(1){t=num%d2;if (t<=9) s2[i]=t+'0'; else s2[i]=t+'A'-10;num/=d2;if (num==0) break;i++;}for (j=0;j<i/2;j++){c=s2[j];s2[j]=s[i-j];s2[i-j]=c;}s2[i+1]='\0';}7.最大公约数、最小公倍数语法:resulet=hcf(int a,int b)、result=lcd(int a,int b)参数:a:int a,求最大公约数或最小公倍数b:int b,求最大公约数或最小公倍数返回值:返回最大公约数(hcf)或最小公倍数(lcd)注意:lcd 需要连同hcf 使用源程序:int hcf(int a,int b){int r=0;while(b!=0){r=a%b;a=b;b=r;}return(a);我也可以做到..10 / 78}lcd(int u,int v,int h){return(u*v/h);}8.组合序列语法:m_of_n(int m, int n1, int m1, int* a, int head)参数:m:组合数C 的上参数n1:组合数C 的下参数m1:组合数C 的上参数,递归之用*a:1~n 的整数序列数组head:头指针返回值:null注意:*a 需要自行产生初始调用时,m=m1、head=0调用例子:求C(m,n)序列:m_of_n(m,n,m,a,0);源程序:void m_of_n(int m, int n1, int m1, int* a, int head){int i,t;if(m1<0 || m1>n1) return;if(m1==n1){return;}m_of_n(m,n1-1,m1,a,head); // 递归调用t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;m_of_n(m,n1-1,m1-1,a,head+1); // 再次递归调用t=a[head];a[head]=a[n1-1+head];a[n1-1+head]=t;}9.快速傅立叶变换(FFT)语法:kkfft(double pr[],double pi[],int n,int k,double fr[],double fi[],intl,int il);参数:我也可以做到..11 / 78pr[n]:输入的实部pi[n]:数入的虚部n,k:满足n=2^kfr[n]:输出的实部fi[n]:输出的虚部l:逻辑开关,0 FFT,1 ifFTil:逻辑开关,0 输出按实部/虚部;1 输出按模/幅角返回值:null注意:需要math.h源程序:void kkfft(pr,pi,n,k,fr,fi,l,il)int n,k,l,il;double pr[],pi[],fr[],fi[];{int it,m,is,i,j,nv,l0; double p,q,s,vr,vi,poddr,poddi;for (it=0; it<=n-1; it++){m=it; is=0;for (i=0; i<=k-1; i++){j=m/2; is=2*is+(m-2*j); m=j;}fr[it]=pr[is]; fi[it]=pi[is];}pr[0]=1.0; pi[0]=0.0;p=6.283185306/(1.0*n);pr[1]=cos(p); pi[1]=-sin(p);if (l!=0) pi[1]=-pi[1];for (i=2; i<=n-1; i++){p=pr[i-1]*pr[1];q=pi[i-1]*pi[1];s=(pr[i-1]+pi[i-1])*(pr[1]+pi[1]);pr[i]=p-q; pi[i]=s-p-q;}for (it=0; it<=n-2; it=it+2){vr=fr[it]; vi=fi[it];fr[it]=vr+fr[it+1]; fi[it]=vi+fi[it+1];fr[it+1]=vr-fr[it+1]; fi[it+1]=vi-fi[it+1]; }m=n/2; nv=2;for (l0=k-2; l0>=0; l0--){我也可以做到..12 / 78m=m/2; nv=2*nv;for (it=0; it<=(m-1)*nv; it=it+nv)for (j=0; j<=(nv/2)-1; j++){p=pr[m*j]*fr[it+j+nv/2];q=pi[m*j]*fi[it+j+nv/2];s=pr[m*j]+pi[m*j];s=s*(fr[it+j+nv/2]+fi[it+j+nv/2]); poddr=p-q; poddi=s-p-q;fr[it+j+nv/2]=fr[it+j]-poddr;fi[it+j+nv/2]=fi[it+j]-poddi;fr[it+j]=fr[it+j]+poddr;fi[it+j]=fi[it+j]+poddi;}}if (l!=0)for (i=0; i<=n-1; i++){fr[i]=fr[i]/(1.0*n);fi[i]=fi[i]/(1.0*n);}if (il!=0)for (i=0; i<=n-1; i++){pr[i]=sqrt(fr[i]*fr[i]+fi[i]*fi[i]);if (fabs(fr[i])<0.000001*fabs(fi[i])) {if ((fi[i]*fr[i])>0) pi[i]=90.0;else pi[i]=-90.0;}elsepi[i]=atan(fi[i]/fr[i])*360.0/6.283185306;}return;}10.Ronberg 算法计算积分语法:result=integral(double a,double b);参数:a:积分上限b:积分下限我也可以做到..13 / 78function f:积分函数返回值:f 在(a,b)之间的积分值注意:function f(x)需要自行修改,程序中用的是sina(x)/x 需要math.h默认精度要求是1e-5源程序:double f(double x){return sin(x)/x; //在这里插入被积函数}double integral(double a,double b){double h=b-a;double t1=(1+f(b))*h/2.0;int k=1;double r1,r2,s1,s2,c1,c2,t2;loop:double s=0.0;double x=a+h/2.0;while(x<b){s+=f(x);x+=h;}t2=(t1+h*s)/2.0;s2=t2+(t2-t1)/3.0;if(k==1){k++;h/=2.0;t1=t2;s1=s2;goto loop;}c2=s2+(s2-s1)/15.0;if(k==2){c1=c2;k++;h/=2.0;t1=t2;s1=s2;goto loop;}r2=c2+(c2-c1)/63.0;if(k==3){r1=r2; c1=c2;k++;h/=2.0;t1=t2;s1=s2;我也可以做到..14 / 78goto loop;}while(fabs(1-r1/r2)>1e-5){ r1=r2;c1=c2;k++;h/=2.0;t1=t2;s1=s2;goto loop;}return r2;}11.行列式计算语法:result=js(int s[][],int n)参数:s[][]:行列式存储数组n:行列式维数,递归用返回值:行列式值注意:函数中常数N 为行列式维度,需自行定义源程序:int js(s,n)int s[][N],n;{int z,j,k,r,total=0;int b[N][N];/*b[N][N]用于存放,在矩阵s[N][N]中元素s[0]的余子式*/if(n>2){for(z=0;z<n;z++){for(j=0;j<n-1;j++)for(k=0;k<n-1;k++)if(k>=z) b[j][k]=s[j+1][k+1]; elseb[j][k]=s[j+1][k];if(z%2==0) r=s[0][z]*js(b,n-1); /*递归调用*/else r=(-1)*s[0][z]*js(b,n-1);total=total+r;}}else if(n==2)total=s[0][0]*s[1][1]-s[0][1]*s[1][0];return total;我也可以做到..15 / 78}12.求排列组合数语法:result=P(long n,long m); / result=long C(long n,long m);参数:m:排列组合的上系数n:排列组合的下系数返回值:排列组合数注意:符合数学规则:m<=n源程序:long P(long n,long m){long p=1;while(m!=0){p*=n;n--;m--;}return p;}long C(long n,long m){long i,c=1;i=m;while(i!=0){c*=n;n--;i--;}while(m!=0){c/=m;m--;}return c;}13.求某一天星期几语法:result=weekday(int N,int M,int d)参数:N,M,d:年月日,例如:2003,11,4返回值:0:星期天,1 星期一……注意:需要math.h适用于1582 年10 月15 日之后, 因为罗马教皇格里高利十三世在这一天启用新历法.源程序:我也可以做到..16 / 78int weekday(int N,int M,int d){int m,n,c,y,w;m=(M-2)%12;if (M>=3) n=N;else n=N-1;c=n/100;y=n%100;w=(int)(d+floor(13*m/5)+y+floor(y/4)+floor(c/4)-2*c)%7;while(w<0) w+=7;return w;}14.卡特兰(Catalan) 数列原理令h(1)=1,catalan 数满足递归式:h(n)= h(1)*h(n-1) + h(2)*h(n-2) + ... + h(n-1)h(1) (其中n>=2)该递推关系的解为:h(n)=c(2n-2,n-1)/n (n=1,2,3,...)1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862, 16796, 58786, 208012, 742900, 2674440,9694845, 35357670, 129644790, 477638700, 1767263190, 6564120420,24466267020, 91482563640, 343059613650, 1289904147324, 4861946401452, …1.括号化问题。
ACM比赛用的简单模板
邵伯仲的模板凸包以斜率为基准的gr法#include<iostream>#include<algorithm>#include<vector>#include<math.h>using namespace std;typedef struct{int x,y;double k;}Node;Node *a;bool cmp(const Node &a,const Node &b)// 根据斜率和x进行排序{if (a.k==b.k) return a.x<b.x;return a.k<b.k;}bool mutiply(const Node &one,const Node &two,const Node &three)//差集{double p1x,p1y,p2x,p2y,result;p1x=two.x-one.x;p1y=two.y-one.y;p2x=three.x-one.x;p2y=three.y-one.y;result=p1x*p2y-p2x*p1y;if (result<=0) return true;return false;}double Area(const Node &one,const Node &two)//计算面积{double p1x,p1y,p2x,p2y,result;p1x=one.x-0;p1y=one.y-0;p2x=two.x-0;p2y=two.y-0;result=(p1x*p2y-p2x*p1y)/2;return result;}int main(){double sum;int last,count;vector <Node>s;Node one,two,three;int n,i,min,t;cin>>t;while(t--){cin>>n;a=new Node[n];sum=0;min=0;for(i=0;i<n;i++){cin>>a[i].x>>a[i].y;if (a[min].x>=a[i].x){if (a[min].x>a[i].x||a[min].y>a[i].y) min=i; }}if (n<3) {cout<<"0.0"<<endl;continue;}for(i=0;i<n;i++)//计算斜率{a[i].k=(double)(a[i].y-a[min].y)/(double)(a[i].x+1-a[min].x); }a[min].k=-2100000000;sort(a,a+n,cmp);//按斜率和x排序s.push_back(a[0]);//开始形成凸包s.push_back(a[1]);for(i=2;i<n;i++){last=s.size();two=s[last-1];one=s[last-2];while(mutiply(one,two,a[i])&&i<n&&s.size()>=2){s.pop_back();if(s.size()==1) break;last=s.size();two=s[last-1];one=s[last-2];}s.push_back(a[i]);}//形成了凸包last=s.size();//计算面积one=s[0];two=s[1];for(i=2;i<last;i++){sum+=Area(one,two);one=two;two=s[i];}sum+=Area(one,two);one=two;two=s[0];sum+=Area(one,two);printf("%.1f\n",sum);s.clear();}return 0;}筛法筛法处理素数#include<iostream>#include<cmath>using namespace std;#define MAX 1001bool la[MAX];void pick(){int i,j;memset(la,1,sizeof(la));la[1]=0;for(i=2;i<=sqrt(double(MAX-1));++i) {if (la[i]){for(j=i*i;j<=MAX-1;j+=i){la[j]=0;}}}}int main(){int i;pick();for(i=1;i<MAX;++i){if (la[i]) printf("%d ",i);}putchar('\n');return 0;}队列的stl实现#include <iostream>#include <queue>#include<vector>int main(){std::queue<int> a;std::priority_queue<int,std::vector<int>,std::less<int> > q;q.push(1);q.push(2);std::cout<<q.top()<<std::endl;return 0;}大数问题1 大数之整数加法#include<iostream>#include<string>using namespace std;string plus(const string &a,const string &b){string result,ttemp;int alen,blen,i,j;int add,temp;alen=a.size();blen=b.size();add=0;for(i=alen-1,j=blen-1;i>=0&&j>=0;i--,j--){temp=add+((int)a[i]-48)+((int)b[j]-48);add=temp/10;ttemp.push_back(temp%10+48);result.insert(0,ttemp);ttemp.clear();}while(i>=0){for(;i>=0;i--){temp=add+(a[i]-48);add=temp/10;ttemp.push_back(temp%10+48);result.insert(0,ttemp);ttemp.clear();}}while(j>=0){for(;j>=0;j--){temp=add+(b[j]-48);add=temp/10;ttemp.push_back(temp%10+48);result.insert(0,ttemp);ttemp.clear();}}if (add!=0){ttemp.push_back(add+48);result.insert(0,ttemp);ttemp.clear();}return result;}int main(){string a,b;a="";while(cin>>b&&b!="0"){a=plus(a,b);}cout<<a<<endl;return 0;}2计算大数小数乘法9位运算#include<iostream>#include<string>#include<cstring>using namespace std;void de0(string &s)//删除无效0{int slen,i;slen=s.length();if (s.find(".")!=-1){i=slen-1;while(s[i]=='0'||s[i]=='.'){if (s[i]=='.') {s.erase(i,1);break;}s.erase(i,1);i--;}}slen=s.length();while(s[0]=='0'&&s[1]!='.'&&slen!=1){s.erase(0,1);slen=s.length();}}int dex(string &multiplicand,string &multiplicator)//统计小数的位数并去掉小数点{int x1,x2,mcandlen,mtorlen,candloca,torloca;mcandlen=multiplicand.length();mtorlen=multiplicator.length();candloca=multiplicand.find(".");torloca=multiplicator.find(".");if (candloca!=-1) {x1=mcandlen-candloca-1;multiplicand.erase(candloca,1); }else x1=0;if (torloca!=-1) {x2=mtorlen-torloca-1;multiplicator.erase(torloca,1);}else x2=0;return x1+x2;}string multiplication( string &multiplicand,string &multiplicator) {int candlen,torlen,i,j,count,candg=0,torg=0,slen;__int64 *result,temp,*get_cand,*get_tor;string ch;string xresult;string str;int xlen;de0(multiplicand);de0(multiplicator);if (multiplicand=="0"||multiplicator=="0") return "0";xlen=dex(multiplicand,multiplicator);candlen=multiplicand.length();torlen=multiplicator.length();get_cand=new __int64[candlen/9+2];get_tor=new __int64[torlen/9+2];memset(get_cand,0,sizeof(get_cand));memset(get_tor,0,sizeof(get_tor));count=1;while (multiplicand.length()>=9){str=multiplicand.substr(multiplicand.length()-9);multiplicand.erase(multiplicand.length()-9);get_cand[count]=atoi(str.c_str());++count;}if (!multiplicand.empty()){str=multiplicand;multiplicand.clear();get_cand[count]=atoi(str.c_str());candg=count;}if (candg==0) candg=count-1;count=1;while (multiplicator.length()>=9){str=multiplicator.substr(multiplicator.length()-9);multiplicator.erase(multiplicator.length()-9);get_tor[count]=atoi(str.c_str());++count;}if (!multiplicator.empty()){str=multiplicator;multiplicator.clear();get_tor[count]=atoi(str.c_str());torg=count;}if (torg==0) torg=count-1;result=new __int64[candg*torg+2];for(i=1;i<=candg*torg+1;i++)result[i]=0;for(i=1;i<=candg;i++){for(j=1;j<=torg;j++){result[i+j-1]+=get_cand[i]*get_tor[j];result[i+j]+=result[i+j-1]/1000000000;result[i+j-1]=result[i+j-1]%1000000000;}}i=candg*torg+1;str.clear();while(result[i]==0) i--;temp=result[i];while(temp){ch.push_back(temp%10+48);str.insert(0,ch);ch.clear();temp/=10;}i--;xresult.append(str);str.clear();while(i>=1){temp=result[i--];while(temp){ch.push_back(temp%10+48);str.insert(0,ch);ch.clear();temp/=10;}slen=(int)str.length();if (slen<9){for(j=1;j<=9-slen;j++){str.insert(0,"0");}}xresult.append(str);str.clear();}if (xlen>0){slen=xresult.length();xresult.push_back(' ');count=0;for(i=xresult.length()-1;i>=0;i--){xresult[i]=xresult[i-1];count++;if (count==xlen) {xresult[i-1]='.';break;}if (count<xlen&&i==1) {xresult.insert(0,"0");i++;}}if (i==1) xresult.insert(0,"0");}de0(xresult);delete[] result;//(比赛时可以考虑不释放以节省时间)delete[] get_cand;delete[] get_tor;return xresult;}int main(){string s,t;while(cin>>s>>t)cout<<multiplication(s,t)<<endl;return 0;}大整数乘法/****** Big Number Multiplication *********************/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000/******************************************************************/ void reverse(char *from, char *to ){int len=strlen(from);int i;for(i=0;i<len;i++)to[i]=from[len-i-1];to[len]='\0';}/******************************************************************/void call_mult(char *first,char *sec,char *result){char F[MAX],S[MAX],temp[MAX];int f_len,s_len,f,s,r,t_len,hold,res;f_len=strlen(first);s_len=strlen(sec);reverse(first,F);reverse(sec,S);t_len=f_len+s_len;r=-1;for(f=0;f<=t_len;f++)temp[f]='0';temp[f]='\0';for(s=0;s<s_len;s++){hold=0;for(f=0;f<f_len;f++){res=(F[f]-'0')*(S[s]-'0') + hold+(temp[f+s]-'0');temp[f+s]=res%10+'0';hold=res/10;if(f+s>r) r=f+s;}while(hold!=0){res=hold+temp[f+s]-'0';hold=res/10;temp[f+s]=res%10+'0';if(r<f+s) r=f+s;f++;}}for(;r>0 && temp[r]=='0';r--);temp[r+1]='\0';reverse(temp,result);}/***************************************************************/int main(){char fir[MAX],sec[MAX],res[MAX];while(scanf("%s%s",&fir,&sec)==2){call_mult(fir,sec,res);int len=strlen(res);for(int i=0;i<len;i++)printf("%c",res[i]);printf("\n");}return 0;}大整数除法//***** Big Number division *********************//#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000/*******************************************************************/ int call_div(char *number,long div,char *result){int len=strlen(number);int now;long extra;char Res[MAX];for(now=0,extra=0;now<len;now++){extra=extra*10 + (number[now]-'0');Res[now]=extra / div +'0';extra%=div;}Res[now]='\0';for(now=0;Res[now]=='0';now++);strcpy(result, &Res[now]);if(strlen(result)==0)strcpy(result, "0");return extra;}/*******************************************************************/ int main(){char fir[MAX],res[MAX];long sec,remainder;while(scanf("%s%ld",&fir,&sec)==2){if(sec==0) printf("Divide by 0 error\n");else{remainder=call_div(fir,sec,res); int len=strlen(res);for(int i=0;i<len;i++)printf("%c",res[i]);printf("\t%ld",remainder); //余数 printf("\n");}}return 0;}大整数加法#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000void reverse(char *from, char *to ){int len=strlen(from);int l;for(l=0;l<len;l++)to[l]=from[len-l-1];to[len]='\0';}void call_sum(char *first, char *sec, char *result){char F[MAX], S[MAX], Res[MAX];int f,s,sum,extra,now;f=strlen(first);s=strlen(sec);reverse(first,F);reverse(sec,S);for(now=0,extra=0;(now<f && now<s);now++){sum=(F[now]-'0') + (S[now]-'0') + extra; Res[now]=sum%10 +'0';extra= sum/10;}for(;now<f;now++){sum=F[now] + extra-'0';Res[now]=sum%10 +'0';extra=sum/10;}for(;now<s;now++){sum=F[now] + extra-'0';Res[now]=sum%10 +'0';extra=sum/10;}if(extra!=0) Res[now++]=extra+'0';Res[now]='\0';if(strlen(Res)==0) strcpy(Res,"0");reverse(Res,result);}int main(){char fir[MAX],sec[MAX],res[MAX];while(scanf("%s%s",&fir,&sec)==2){call_sum(fir,sec,res);int len=strlen(res);for(int i=0;i<len;i++) printf("%c",res[i]);printf("\n");}return 0;}大整数减法/***** Big Number Subtraction *******************/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000/*******************************************************************/ void reverse(char *from, char *to ){int len=strlen(from);int l;for(l=0;l<len;l++)to[l]=from[len-l-1];to[len]='\0';}int call_minus(char *large, char *small, char *result){char L[MAX], S[MAX];int l,s,now,hold,diff;l=strlen(large);s=strlen(small);bool sign = 0;if(l<s){strcpy(result,large);strcpy(large,small);strcpy(small,result);now=l; l=s; s=now;sign = 1;}//return 0;if(l==s){if(strcmp(large, small)<0){strcpy(result,large);strcpy(large,small);strcpy(small,result);now=l; l=s; s=now;sign =1;}//return 0;}reverse(large,L);reverse(small,S);for(;s<l;s++)S[s]='0';S[s]='\0';for(now=0,hold=0;now<l;now++){diff=L[now]-(S[now]+hold);if(diff<0){hold=1;result[now]=10+diff+'0'; }else{result[now]=diff+'0';hold=0;}}for(now=l-1;now>0;now--){if(result[now]!='0')break;}result[now+1]='\0';reverse(result,L);strcpy(result,L);//return 1;return sign;}int main(){char fir[MAX],sec[MAX],res[MAX];while(scanf("%s%s",&fir,&sec)==2){if(call_minus(fir,sec,res)==1) printf("-");int len = strlen(res);for(int i=0;i<len;i++)printf("%c",res[i]);printf("\n");}return 0;}大整数开平方根//****** Big Number Sqrt ************************//#include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>#define MAX 1000/******************************************************************/ void reverse(char *from, char *to ){int len=strlen(from);int i;for(i=0;i<len;i++)to[i]=from[len-i-1];to[len]='\0';}/****************************************************************/ int call_minus(char *large, char *small, char *result){char L[MAX], S[MAX];int l,s,now,hold,diff;l=strlen(large);s=strlen(small);if(l<s)return 0;if(l==s){if(strcmp(large, small)<0)return 0;}reverse(large,L);reverse(small,S);for(;s<l;s++)S[s]='0';S[s]='\0';for(now=0,hold=0;now<l;now++){diff=L[now]-(S[now]+hold);if(diff<0){hold=1;result[now]=10+diff+'0';}else{result[now]=diff+'0';hold=0;}}for(now=l-1;now>0;now--){if(result[now]!='0')break;}result[now+1]='\0';reverse(result,L);strcpy(result,L);return 1;}/******************************************************************/ void call_mult(char *first,char *sec,char *result){char F[MAX],S[MAX],temp[MAX];int f_len,s_len,f,s,r,t_len,hold,res;f_len=strlen(first);s_len=strlen(sec);reverse(first,F);reverse(sec,S);t_len=f_len+s_len;r=-1;for(f=0;f<=t_len;f++)temp[f]='0';temp[f]='\0';for(s=0;s<s_len;s++){hold=0;for(f=0;f<f_len;f++){res=(F[f]-'0')*(S[s]-'0') + hold+(temp[f+s]-'0');temp[f+s]=res%10+'0';hold=res/10;if(f+s>r) r=f+s;}while(hold!=0){res=hold+temp[f+s]-'0';hold=res/10;temp[f+s]=res%10+'0';if(r<f+s) r=f+s;f++;}}for(;r>0 && temp[r]=='0';r--);temp[r+1]='\0';reverse(temp,result);}/****************************************************************/ void call_sqrt(char *number,char *result,char *extra){int num,start,e,mul,l,r=0,len;char left[MAX],after[MAX];char who[5],temp[MAX],two[5];len=strlen(number);if(len%2==0){num=10*(number[0]-'0') + number[1]-'0';start=2;}else{num=number[0]-'0';start=1;}mul=(int) sqrt(num);result[0]=mul+'0';result[1]='\0';if(num-mul*mul ==0)extra[0]='\0';elsesprintf(extra,"%d",num-mul*mul);for(;start<len;start+=2){e=strlen(extra);extra[e]=number[start];extra[e+1]=number[start+1];extra[e+2]='\0';two[0]='2';two[1]='\0';call_mult(result,two,left);l=strlen(left);for(mul=9;mul>=0;mul--){who[0]=mul+'0';who[1]='\0';strcat(left,who);call_mult(left,who,after);if(call_minus(extra,after,temp)==1){result[++r]=mul+'0';result[r+1]='\0';strcpy(extra,temp);break;}elseleft[l]='\0';}}result[++r]='\0';}/******************************************************************/ int main(){char fir[MAX],ex[MAX],res[MAX];while(scanf("%s",&fir)==1){call_sqrt(fir,res,ex);int len=strlen(res);for(int i=0;i<len;i++) printf("%c",res[i]);printf("\n");}return 0;}孩子报数问题:#include<stdio.h>#include<string.h>typedef struct{char name[16];}Name;int main(){Name child[65];int n,count,i,j,k;scanf("%d",&n);for(i=1;i<=n;i++){scanf("%s",&child[i].name);}scanf("%d,%d",&count,&k);for(i=n;i>=2;--i){count=(count+k-1)%i;if (count==0) count=i;printf("%s\n",child[count].name);for(j=count;j<i;++j){strcpy(child[j].name,child[j+1].name);}}printf("%s\n",child[1].name);return 0;}统计难题:Ignatius最近遇到一个难题,老师交给他很多单词(只有小写字母组成,不会有重复的单词出现),现在老师要他统计出以某个字符串为前缀的单词数量(单词本身也是自己的前缀).输入输入数据的第一部分是一张单词表,每行一个单词,单词的长度不超过10,它们代表的是老师交给Ignatius统计的单词,一个空行代表单词表的结束.第二部分是一连串的提问,每行一个提问,每个提问都是一个字符串.注意:本题只有一组测试数据,处理到文件结束.输出对于每个提问,给出以该字符串为前缀的单词的数量.样例输入bananabandbeeabsoluteacmbabbandabc样例输出231字典树解决:#include<iostream>#include<string.h>using namespace std;typedef struct Node{char letter;bool la;struct Node *child;struct Node *brother;int count;}Elem;void creat(Elem *head,char *word){Elem *p,*q,*r;int i;bool suc;p=head;for(i=0;i<(int)strlen(word);i++){suc=false;q=p->child;r=q;while(q){r=q;if (q->letter==word[i]) {suc=true;p=q;p->count++;break;}q=q->brother;}if (suc) continue;q=new Elem;q->letter=word[i];q->count=1;q->brother=NULL;q->child=NULL;q->la=false;if (!p->child) p->child=q;if (r) r->brother=q;p=q;}}int find_1(Elem head,char *word){Elem *p,*q;int i;p=&head;for(i=0;i<(int)strlen(word);i++){q=p->child;while(q){if (q->letter==word[i]) {break;}q=q->brother;}if (!q) return 0;p=q;}return p->count;}int main(){char word[10];Elem head;head.letter=0;head.child=NULL;head.brother=NULL;=true;head.count=0;while(gets(word),strcmp(word,"")!=0){creat(&head,word);}while(scanf("%s",word)!=EOF){printf("%d\n",find_1(head,word));}return 0;}21。
山东的大学ACM模板
上海大学 ACM 模板 by kuangbin
图论 ................................................................................................................................ 69 1、最短路 ...................................................................................................................... 69 2、最小生成树 .............................................................................................................. 72 3、次小生成树 .............................................................................................................. 74 4、有向图的强连通分量 .............................................................................................. 75 5、图的割点、桥和双连通分支的基本概念............................................................... 77 6、割点与桥 .................................................................................................................. 78 7、边双连通分支 .......................................................................................................... 81 8、点双连通分支 .......................................................................................................... 83 9、最小树形图 .............................................................................................................. 85 10、二分图匹配 ............................................................................................................ 87 11、生成树计数 ............................................................................................................ 91 11、二分图多重匹配 .................................................................................................... 94 12、KM 算法(二分图最大权匹配) .......................................................................... 94 13、最大流 .................................................................................................................... 96 14、最小费用最大流 .................................................................................................. 100 15、2-SAT ..................................................................................................................... 102 16、曼哈顿最小生成树 .............................................................................................. 105 17、一般图匹配带花树 .............................................................................................. 107 18、LCA ........................................................................................................................ 110 19、欧拉路 .................................................................................................................. 115 计算几何 ...................................................................................................................... 121 1、基本函数 ................................................................................................................ 121 2、凸包 ........................................................................................................................ 126 3、平面最近点对(HDU 1007) ................................................................................ 127 4、旋转卡壳 ................................................................................................................ 128 5、半平面交 ................................................................................................................ 133 6、三点求圆心坐标(三角形外心)......................................................................... 136 7、求两圆相交的面积 ................................................................................................ 136 8、Pick 公式 .................................................................................... 137 动态规划 ...................................................................................................................... 137 1、最长上升子序列 O(nlogn) ..................................................................................... 137 搜索 .............................................................................................................................. 138
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
目录1.最小生成树 (2)2.最短路算法 (7)3.素数打表 (11)4.最大匹配 (12)5.线段树(敌兵布阵) (14)6.线段树(逆序树) (16)7.树形dp (18)8.树状数组(段跟新) (20)9.Kmp模板 (22)10.线段树(点跟新) (26)11.强连通 (28)12.最小割 (31)13.单源最短路(spfa) (34)14.三分查找 (36)15.字典树(统计难题) (38)16.最大流入门题1273 (40)17.状态压缩 (43)18.匈牙利(HDU 2063)(最大匹配) (45)19.凸包(HDU1348) (47)20.树状数组(HDU1166) (50)21.强连通 (52)22.前向星 (55)23.矩阵 (58)24.并查集 (60)25. SORT (61)26. STL (63)27. LCA (HDU 2874) (67)28. 01背包 (70)29. 状态压缩代码: (72)30. 快速幂 (74)31.矩阵快速幂 (75)32.GCD & LCM (77)33.ACM小技巧: (78)34. /** 大数(高精度)求幂**/ (80)35. /** 大数除法与求余**/ (82)36. /** 大数阶乘**/ (84)37. /** 大数乘法**/ (85)38. /** 大数累加**/ (86)1.最小生成树要连通n个城市需要n-1条边线路。
可以把边上的权值解释为线路的造价。
则最小生成树表示使其造价最小的生成树。
prim算法(矩阵形式):#define inf 0x3f3f3f3fint prim(int n,int sta)//n表示有n个顶点,sta表从sta这个顶点出发生成最小生成树{int mark[M],dis[M];int i,sum = 0; //sum是总的最小生成树边权值for (i = 0;i < n;i ++) //初始化dis[i] 表从顶点sta到点i的权值 {dis[i] = mat[sta][i];mark[i] = 0;}mark[sta] = 1; //sta 这个顶点加入最小生成树中 for (i = 1;i < n;i ++) //循环n-1次,每次找出一条最小权值的边 n个点的图{ //只有n-1条边int min = inf; //inf 表无穷大for (j = 0;j < n;j ++)//找出当前未在最小生成树中边权最小的顶点if (!mark[j] && dis[j] < min)min = dis[j],flag = j;mark[flag] = 1; //把该顶点加入最小生成树中sum += dis[flag]; //sum加上其边权值for (j = 0;j < n;j ++) //以falg为起点更新到各点是最小权值if (dis[j] > mat[flag][j])dis[j] = mat[flag][j];}return sum; //返回边权总和}prim算法(边表形式):struct Edge//frm为起点,to为终点,w为边权,nxt指向下一个顶点{// int frm;int to,w,nxt;}edge[M];int vis[M],head[M],dis[M];void addedge (int cu,int cv,int cw)//生成边的函数{//edge[e].frm = cu;edge[e].to = cv;edge[e].w = cw;edge[e].nxt = head[cu];head[cu] = e ++;//edge[e].frm = cv;edge[e].to = cu;edge[e].w = cw;edge[e].nxt = head[cv];head[cv] = e ++;}int prim(int n,int sta) //n为顶点数量,sta为起点{int sum = 0;memset(dis,0x3f,sizeof(dis));memset(vis,0,sizeof(vis));for (i = head[sta];i != -1;i = edge[i].nxt)//遍历与sta点相连的所有顶点 {int v = edge[i].to;dis[v] = edge[i].w;}vis[sta] = 1; //加入到最小生成树中int m = n - 1; //只生成n-1条边,所以循环n-1次while (m --){int min = inf;for (i = 0;i < n;i ++)//找出当前边权最小的边if (!vis[i]&&dis[i] < min)flag = i,min = dis[i];sum += dis[flag];vis[flag] = 1;//加入到最小生成树中for (i = head[flag];i != -1;i = edge[i].nxt) //更新与flag顶点相连的点的dis{int v = edge[i].to;if (edge[i].w < dis[v])dis[v] = edge[i].w;}}return sum; //返回边权总和}int main (){e = 0; //记得初始化memset (head,-1,sizeof(head));scanf ("%d %d %d",&a,&b,&w);addedge(a,b,w);..........prim(n,sta);return 0;}Kruskal算法:struct Edge{int v1,v2,w;}edge[M],tree[M]; //w为v1顶点到v2顶点的边权/ *int Find (int parent[],int u)//第1种写法{int tmp = u;while (paren[tmp] != -1)tmp = parent[tmp];return tmp;}*/int Find (int u) //第2种写法{if (u != parent[u])parent[u] = Find(paren[u]);return parent[u];}bool cmp (Edge a,Edge b){return a.w < b.w;}int Kruskal()//parent[]表示集合{int parent[M];int i,j,sum,vf1,vf2;sort(edge,edge+E,cmp);// memset (parent,-1,sizeof(parent));//对应第1种并查集的初始化for (i = 0;i < n;i ++) //对应第2种并查集的初始化parent[i] = i;sum = i = j = 0;while (i < E && j < N - 1)//生成的边数为N-1{vf1 = Find(parent,edge[i].v1); //找这两个点的祖先vf2 = Find(parent,edge[i].v2);if (vf1 != vf2) //若两个点的祖先不同,说明不在同一集合{parent[vf2] = vf1;//把vf2点加到vf1点的集合中tree[j++] = edge[i];//把边加到tree[]数组中,这句题目没要求可忽略之sum += edge[i].w; //sum 加上其边权}i ++;}return sum;}最小生成树 -- Kruskal算法:运用数组存点与边的权值#include <stdio.h>#include <stdlib.h>#include <algorithm>#define N 150using namespace std;int m,n,u[N],v[N],w[N],p[N],r[N];int cmp(const int i,const int j) {return w[i]<w[j];} int find(int x) {return p[x]==x?x:p[x]=find(p[x]);}int kruskal(){int cou=0,x,y,i,ans=0;for(i=0;i<n;i++) p[i]=i;for(i=0;i<m;i++) r[i]=i;sort(r,r+m,cmp);for(i=0;i<m;i++){int e=r[i];x=find(u[e]);y=find(v[e]);if(x!=y) {ans += w[e];p[x]=y;cou++;}}if(cou<n-1) ans=0;return ans;}int main(){int i,ans;while(scanf("%d%d",&m,&n)!=EOF&&m){for(i=0;i<m;i++){scanf("%d%d%d",&u[i],&v[i],&w[i]);}ans=kruskal();if(ans) printf("%d\n",ans);else printf("?\n",ans);}return 0;}2.最短路算法①DIJKC++代码1.#define inf0x3fffffff2.#define M1053.4.int dist[M],map[M][M],n;5.bool mark[M];6.7.void init()8.{9.int i,j;10.for(i=1;i<=n;i++)//i==j的时候也可以初始化为0,只是有时候不合适11.for(j=1;j<=n;j++)12.map[i][j]=inf;13.}14.15.void dijk(int u)16.{17.int i,j,mins,v;18.for(i=1;i<=n;i++)19.{20.dist[i]=map[u][i];21.mark[i]=false;22.}23.mark[u]=true;24.dist[u]=0;//既然上面的map当i==j时不是0,就要这句25.while(1)26.{27.mins=inf;28.for(j=1;j<=n;j++)29.if(!mark[j]&&dist[j]<mins)30.mins=dist[j],v=j;31.if(mins==inf)32.break;33.mark[v]=true;34.for(j=1;j<=n;j++)35.if(!mark[j]&&dist[v]+map[v][j]<dist[j])36.dist[j]=dist[v]+map[v][j];37.}38.}②Floyd1.#define inf0x3fffffff//注意,太大会溢出2.#define M//最大点数3.int n,dist[M][M];//n:实际点数4.5.void init()//有时候需要初始化6.{7.int i,j;8.for(i=1;i<=n;i++)9.for(j=i+1;j<=n;j++)10.dist[i][j]=dist[j][i]=inf;11.}12.13.void floyd()14.{15.int i,j,k;16.for(k=1;k<=n;k++)17.for(i=1;i<=n;i++)18.for(j=1;j<=n;j++)//有的题目会溢出就要自己变通了19.if(dist[i][k]+dist[k][j]<dist[i][j])20.dist[i][j]=dist[i][k]+dist[k][j];21.}③vector后插的SPFAC++代码1.#define inf0x3fffffff2.#define M105//最大点数3.struct son{4.int v,w;5.};6.vector<son>g[M];7.bool inq[M];//入队列标记8.int dist[M],n;//n:实际点数9.10.void init()11.{12.for(int i=1;i<=n;i++)13.g[i].clear();14.}15.16.void spfa(int u)17.{18.int i,v,w;19.for(i=1;i<=n;i++)20.{21.dist[i]=inf;22.inq[i]=false;23.}24.queue<int>q;25.q.push(u);26.inq[u]=true;27.dist[u]=0;28.while(!q.empty())29.{30.u=q.front();31.q.pop();32.inq[u]=false;33.for(i=0;i<g[u].size();i++)34.{35.v=g[u][i].v;36.w=g[u][i].w;37.if(dist[u]+w<dist[v])38.{39.dist[v]=dist[u]+w;40.if(!inq[v])41.{42.q.push(v);43.inq[v]=true;44.}45.}46.}47.}48.}④模拟前插的SPFA(多数情况下比③快,数据较为复杂就会看出来) C++代码1.#define inf0x3fffffff2.#define M1005//最大点数3.4.struct edge{5.int v,w,next;6.}e[10005];//估计好有多少条边7.8.int pre[M],t,dist[M],n;9.bool inq[M];10.//注意初始化11.void init()12.{13.t=0;14.memset(pre, -1,sizeof(pre));15.}16.//注意双向加边17.void addedge(int u,int v,int w)//加边函数,慢慢模拟就会明白的18.{19.e[cnt].v=v;20.e[cnt].w=w;21.e[cnt].next=pre[u];//接替已有边22.pre[u]=t++;//自己前插成为u派生的第一条边23.}24.25.void spfa(int u)26.{27.int v,w,i;28.for(i=1;i<=n;i++)//对于从1到n的编号29.dist[i]=inf,inq[i]=false;30.dist[u]=0;31.queue<int>q;32.q.push(u);33.inq[u]=true;34.while(!q.empty())35.{36.u=q.front();37.q.pop();38.inq[u]=false;39.for(i=pre[u];i!= -1;i=e[i].next)40.{41.w=e[i].w;42.v=e[i].v;43.if(dist[u]+w<dist[v])44.{45.dist[v]=dist[u]+w;46.if(!inq[v])47.{48.q.push(v);49.inq[v]=true;50.}51.}52.}53.}54.}3.素数打表#include<iostream>#include<cstring>#include<cmath>#define MAXN 5000using namespace std;int prime[MAXN];void print_prime(){int n = (int) sqrt(MAXN);for(int i = 2; i < n; i++){if( !prime[i] ){for(int j = i*i; j < MAXN; j += i)prime[j] = 1;prime[++prime[0]] = i;}}for(int i = n; i < MAXN; i++)if(!prime[i])prime[++prime[0]] = i;}int main(){FILE *out;out = fopen("out.txt","w");print_prime();for(int i = 1; i <= prime[0]; i++)fprintf(out, "%d,", prime[i]);return 0;}4.最大匹配#include<stdio.h>#include<string.h>#define MAX 505bool used[MAX];bool match[MAX][MAX];int boys[MAX],girls[MAX];int k, n;void init(){memset(girls, -1, sizeof(girls));memset(boys, -1, sizeof(boys));memset(match, false, sizeof(match));}bool can(int t){int i;for(i = 0; i < n; i ++){if(!used[i] && match[t][i]){used[i] = true;if(girls[i] = = -1 || can(girls[i])){boys[t] = i;girls[i] = t;return true;}}}return false;}int main(){int tmpa, tmpb, i, res, t;while(scanf("%d", &n) != EOF){init();for(i = 0; i < n; ++i){scanf("%d: (%d)", &tmpa, &k);while(k--){scanf("%d", &tmpb);match[tmpa][tmpb] = true;res = 0;for(i = 0; i < n; i++){if(boys[i] == -1){memset(used, false, sizeof(used));if(can(i)) res ++;}}}}printf("%d\n", n - res/2);}return 0;}5.线段树(敌兵布阵)#include<stdio.h>#include<string.h>int a[50005],n;void update(int x,int c){int i;for(i=x;i<=n;i+=(i&(-i)))a[i]+=c;}int s(int x){int i;int sum=0;for(i=x;i>0;i-=(i&-i)){sum+=a[i];}return sum;}int main(){int t,i,c,b=1;int z,y;char sh[15];scanf("%d",&t);while(t--){memset(a,0,sizeof(a));scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&c);update(i,c);}printf("Case %d:\n",b++);while(~scanf("%s",sh)){if(sh[0]=='E')break;scanf("%d%d",&z,&y);if(sh[0]=='A')update(z,y);else if(sh[0]=='S')update(z,-y);else printf("%d\n",s(y)-s(z-1));}}return 0;}6.线段树(逆序树)#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int a[500005],n;int b[500005];int d[500005];void update(int x,int c){int i;for(i=x;i<=n;i+=(i&(-i)))a[i]+=c;}int s(int x){int i;int sum=0;for(i=x;i>0;i-=(i&-i)){sum+=a[i];}return sum;}int main(){int i,j;int ans;while(scanf("%d",&n)!=EOF,n){memset(d,0,sizeof(d));for(i=1;i<=n;i++){scanf("%d",&b[i]);b[i]=b[i]+1;d[i]=b[i];}sort(b+1,b+n+1);memset(a,0,sizeof(a));ans=0;for(i=1;i<=n;i++){update(d[i],1);printf("%d ",s(d[i]));ans+=i-s(d[i]);printf("%d ",ans);}printf("%d\n",ans);}return 0;}7.树形dp#include<stdio.h>#include<iostream>using namespace std;struct Tree{int father,child,brother,with_max,without_max;int MAX(){return with_max>=without_max?with_max:without_max;}void init(){father=child=brother=without_max=0;}}tree[6001];void dfs(int id){int child;child=tree[id].child;while(child){dfs(child);tree[id].with_max+=tree[child].without_max;tree[id].without_max+=tree[child].MAX();child=tree[child].brother;}}int main(){int n,i;while(scanf("%d",&n)!=EOF){for(i=1;i<=n;i++){scanf("%d",&tree[i].with_max);tree[i].init();}int a,b;while(scanf("%d%d",&a,&b),a||b){tree[a].father=b;tree[a].brother=tree[b].child;tree[b].child=a;}for(i=1;i<n;i++)if(!tree[i].father){dfs(i);printf("%d\n",tree[i].MAX());break;}}return 0;}8.树状数组(段跟新)1.#include<stdio.h>2.#include<string.h>3.const int MAXN=110000;4.int n,c[MAXN];5.int lowbit(int x)6.//计算2^k7.{8.x=x&-x;9.return x;10.}11.void update(int num,int val)12.//向下查询,num是要更新的子节点,val是要修改的值13.{14.while(num>0)15.{16.c[num]+=val;17.num-=lowbit(num);18.}19.}20.int getSum(int num)21.//向上统计每个区间被染色的次数22.{23.int sum=0;24.while(num<=n)25.{26.sum+=c[num];27.num+=lowbit(num);28.}29.return sum;30.}31.int main()32.{33.int a,b;34.while(scanf("%d",&n),n)35.{36.memset(c,0,sizeof(c));37.for(int i=0;i<n;i++)38.{39.scanf("%d%d",&a,&b);40.//将b以下区间+141.update(b,1);42.//将a以下区间-143.update(a-1,-1);44.}45.for(int j=1;j<n;j++)46.{47.printf("%d",getSum(j));48.}49.printf("%d\n",getSum(n));50.}51.return0;52.}9.Kmp模板#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#define N 1000010int len,len1,next[N];int str[N],str1[N];void get_next(){int i=0,j=-1;next[0]=-1;while(i<=len1){if(j==-1||str1[i]==str1[j]){i++;j++;next[i]=j;}elsej=next[j];}}int kmp(){int i=0,j=0;{if(j==-1||str[i]==str1[j]){i++;j++;}else{j=next[j];}}if(j>=len1){return i-len1+1;}return 0;}int main(){int i,t,flag;scanf("%d",&t);while(t--){memset(str,0,sizeof(str));memset(str1,0,sizeof(str1));memset(next,0,sizeof(next));scanf("%d%d",&len,&len1);for(i=0;i<len;i++)scanf("%d",&str[i]);for(i=0;i<len1;i++)scanf("%d",&str1[i]);get_next();flag=kmp();// printf("%d\n",flag);if(flag==0)printf("-1\n");elseprintf("%d\n",flag);}return 0;}计算出字符串 str2 中含有的 str1 的个数#include<stdio.h>#include<string.h>int next[10005];char str1[10005], str2[1000005];int n, m, ans;void getNext(char *p, int *next){int j, k;next[0] = -1;j = 0;k = -1;while(j < m){if(k == -1 || p[j] == p[k]) //匹配的情况下,p[j]==p[k]{j++;k++;next[j] = k;//printf("%d **%d **%d\n",j, k, next[j]);}else //p[j]!=p[k]k = next[k];}}int KMPMatch(char *s, char *p){int i = 0, j = 0;getNext(p, next);/*for(i = 1; i < m; i++) printf("%d ", next[i]);i = 0; printf("\n");*/while(i < n){if(j == -1 || s[i] == p[j]){i++;j++;}else{j = next[j]; //消除了指针i的回溯printf("i = %d, j = %d\n", i, j),}if(j == m )ans++;//return i - m + 1;}return ans;}int main(){int T;scanf("%d",&T);while(T--){memset(str1, '\0', sizeof(str1));memset(str2, '\0', sizeof(str2));memset(next, 0, sizeof(next));ans = 0;scanf("%s", str1);scanf("%s", str2);n = strlen(str2);m = strlen(str1);printf("%d\n",KMPMatch(str2, str1));}return 0;}10.线段树(点跟新)#include<stdio.h>#include<string.h>#define N 200010struct Node{int l,r,max;}node[3*N];int score[N];int max(int a,int b){return a>b?a:b;}void Build(int left,int right,int index){node[index].l=left;node[index].r=right;if(left==right)node[index].max=score[left];else{int mid;mid=(left+right)/2;Build(left,mid,index*2);Build(mid+1,right,index*2+1);node[index].max=max(node[2*index].max,node[2*index+1].max);}}void Update(int stu,int c,int index){node[index].max=max(c,node[index].max);if(node[index].l==node[index].r){return ;}if(stu<=node[2*index].r){Update(stu,c,index*2);}else{Update(stu,c,index*2+1);}}int query(int left,int right,int index){if(left==node[index].l&&right==node[index].r){return node[index].max;}if(right<=node[2*index].r){return query(left,right,index*2);}if(left>=node[2*index+1].l){return query(left,right,index*2+1);}int mid=(node[index].l+node[index].r)/2;return max(query(left,mid,2*index),query(mid+1,right,index*2+1)); }int main(){int n,m;while(scanf("%d%d",&n,&m)!=EOF){int i;for(i=1;i<=n;i++)scanf("%d",&score[i]);getchar();char c;int s,e;Build(1,n,1);for(i=0;i<m;i++){scanf("%c%d%d",&c,&s,&e);getchar();if(c=='U'){Update(s,e,1);}if(c=='Q'){printf("%d\n",query(s,e,1));}}}return 0;11.强连通# include<stdio.h># include<string.h># define N 1005# define M 2005struct node{int from,to,next;}edge1[M],edge2[M];int visit1[N],visit2[N],head1[N],head2[N],T[N];int in_degree[N],out_degree[N],tol1,tol2,Bcnt,Tcnt;int val[N],v1[N],min,Belong[N];void add(int a,int b){edge1[tol1].from=a;edge1[tol1].to=b;edge1[tol1].next=head1[a];head1[a]=tol1++;edge2[tol2].from=b;edge2[tol2].to=a;edge2[tol2].next=head2[b];head2[b]=tol2++; }void dfs1(int x){int i;visit1[x]=1;for(i=head1[x];i!=-1;i=edge1[i].next)if(visit1[edge1[i].to]==0) dfs1(edge1[i].to);T[Tcnt++]=x;}void dfs2(int x){int i;Belong[x]=Bcnt;if(val[x]<min) min=val[x];visit2[x]=1;for(i=head2[x];i!=-1;i=edge2[i].next)if(visit2[edge2[i].to]==0) dfs2(edge2[i].to);}int main(){int i,n,m,sum,x,y,a,b,count;while(scanf("%d%d",&n,&m)!=EOF){tol1=tol2=0;Bcnt=Tcnt=0;for(i=1;i<=n;i++){head1[i]=-1;head2[i]=-1;visit1[i]=0;visit2[i]=0;scanf("%d",&val[i]);}while(m--){scanf("%d%d",&a,&b);add(a,b);}for(i=1;i<=n;i++)if(visit1[i]==0) dfs1(i);for(i=Tcnt-1;i>=0;i--){if(visit2[T[i]]==0){min=0xfffffff;dfs2(T[i]);v1[Bcnt]=min;Bcnt++;}}for(i=0;i<Bcnt;i++){in_degree[i]=0;out_degree[i]=0;}for(i=0;i<tol1;i++){x=Belong[edge1[i].from];y=Belong[edge1[i].to];if(x!=y){in_degree[y]=1;out_degree[x]=1;}}sum=0;count=0;for(i=0;i<Bcnt;i++){if(in_degree[i]==0) {sum+=v1[i];count++;} }printf("%d %d\n",count,sum);}return 0;}12.最小割#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#include<math.h>#define oo 10000000#define M 1000000#define N 100000using namespace std;int head[N],mark[N],work[N],Q[M];int map[205][205],dist[N];int tot,src,dest,n,m;struct node{int to,cap,next;}edge[M];void add(int a,int b,int c,int d){edge[tot].to=b,edge[tot].cap=c,edge[tot].next=head[a],head[a]=tot++;edge[tot].to=a,edge[tot].cap=d,edge[tot].next=head[b],head[b]=tot++; }int min(int a,int b){return a<b?a:b;}bool BFS(){int i,j,k,l,h,y;for(i=src;i<=dest;i++)dist[i]=-1;dist[src]=0;l=h=0;Q[l++]=src;while(h<l){k=Q[h++];for(i=head[k];i!=-1;i=edge[i].next){y=edge[i].to;if(edge[i].cap>0&&dist[y]==-1){dist[y]=dist[k]+1;Q[l++]=y;}}}return (dist[dest]>=0);}int DFS(int x,int exp){mark[x]=-1;if(x==dest)return exp;for(int temp,y,i=work[x];i!=-1;i=edge[i].next,work[x]=i) {y=edge[i].to;if(edge[i].cap>0&&dist[y]==dist[x]+1&&!mark[y]){if((temp=DFS(y,min(edge[i].cap,exp)))>0){edge[i].cap-=temp;edge[i^1].cap+=temp;return temp;}}}return 0;}int Dinic_flow(){int ans=0,flow,i;while(BFS()){for(i=0;i<=dest;i++)work[i]=head[i];while(1){for(i=0;i<=dest;i++)mark[i]=0;flow=DFS(src,oo);if(flow==0)break;ans+=flow;}}return ans;}int main(){int i,j,x,y,k,v=1;while(scanf("%d%d",&n,&m)!=EOF){for(i=1;i<=n;i++)for(j=1;j<=m;j++)scanf("%d",&map[i][j]);memset(head,-1,sizeof(head));tot=0;src=0;dest=n*m+1;for(i=1;i<=n;i++)for(j=1;j<=m;j++){if(j+1<=m)add((i-1)*m+j,(i-1)*m+j+1,1,1);if(i+1<=n)add((i-1)*m+j,i*m+j,1,1);if(map[i][j]==1)add(src,(i-1)*m+j,oo,0);else if(map[i][j]==2)add((i-1)*m+j,dest,oo,0);}printf("Case %d:\n%d\n",v++,Dinic_flow());}return 0;}13.单源最短路(spfa)#include<stdio.h>#include<string.h>#include<stdlib.h>#include<queue>#define false 0#define true 1using namespace std;const int maxn=100000;const int inf=0x7ffffff;struct edge{int from,to,w,p,next;}e[100001];int head[maxn];int vis[maxn];int dist[maxn];int cost[maxn];int n,m,t,sum;void add(int i,int j,int w,int p){ e[t].from=i;e[t].to=j;e[t].w=w;e[t].p=p;e[t].next=head[i];head[i]=t++;}void spfa(int s){queue<int> q;for(int i=1;i<=n;i++){dist[i]=inf;cost[i]=inf;}memset(vis,false,sizeof(vis));q.push(s);dist[s]=0;cost[s]=0;while(!q.empty()){int u=q.front();q.pop();vis[u]=false;for(int i=head[u];i!=-1;i=e[i].next){int v=e[i].to;if(dist[v]>dist[u]+e[i].w){dist[v]=dist[u]+e[i].w;cost[v]=cost[u]+e[i].p;if(!vis[v]){vis[v]=true;q.push(v);}}if(dist[v]==dist[u]+e[i].w&&cost[v]>cost[u]+e[i].p)cost[v]=cost[u]+e[i].p;}}}int main(){int a,b,c,s,e,p;while(scanf("%d%d",&n,&m)!=EOF,n,m){t=0;memset(head,-1,sizeof(head));while(m--){scanf("%d%d%d%d",&a,&b,&c,&p);add(a,b,c,p);add(b,a,c,p);}scanf("%d%d",&s,&e);spfa(s);printf("%d %d\n",dist[e],cost[e]);}return 0;}14.三分查找static bool Find(int[] sortedArray, int number){if (sortedArray.Length == 0)return false;int start = 0;int end = sortedArray.Length - 1;while (end >= start){int firstMiddle = (end - start) / 3 + start;int secondMiddle = end - (end - start) / 3;if (sortedArray[firstMiddle] > number)end = firstMiddle - 1;else if (sortedArray[secondMiddle] < number)start = secondMiddle + 1;else if (sortedArray[firstMiddle] != number && sortedArray[secondMiddle] != number){end = secondMiddle - 1;start = firstMiddle + 1;}elsereturn true;}return false;}二分查找int binary_search(int* a, int len, int goal) {int low = 0;int high = len - 1;while(low <= high){int middle = (low + high)/2;if(a[middle] == goal)return middle;//在左半边else if(a[middle] > goal)high = middle - 1;//在右半边elselow = middle + 1;}//没找到return -1;}15.字典树(统计难题)#include<stdio.h>#include<string.h>#include <stdlib.h>//typedef struct Node;struct Node{int num;struct Node *next[26];};struct Node *root;void Insert(char *s){struct Node *p, *q;int i = 0, len = strlen(s);p = root;while( i < len){if( p->next[s[i] - 'a'] != NULL){p = p ->next[s[i] - 'a'];p -> num++;}else{q = (Node *)malloc( sizeof( Node));memset( q, NULL, sizeof(Node));p->next[s[i] - 'a'] = q;p = q;p -> num++;}i++;}}int Select(char *s){Node *p;int i = 0, len = strlen(s);p = root;while( (p!=NULL) && i < len){if( p->next[s[i] - 'a'] != NULL){p = p->next[s[i] - 'a'];}else break;i++;}if(p != NULL && i == len) return p->num;else return 0;}int main(){int n, m, i;char s1[15],s2[15];root = (struct Node*)malloc(sizeof(struct Node));memset(root,NULL,sizeof(struct Node));while(~scanf("%d", &n)){getchar();for(i = 1; i <= n; i++){gets(s1);if(s1[0] == '\0') break;Insert(s1);}scanf("%d",&m);getchar();for(i = 1; i <= m; i++){gets(s2);printf("%d\n",Select(s2));}}return 0;}16.最大流入门题 1273可增广路径所谓可增广路径,是指这条路径上的流可以修改,通过修改,使得整个网络的流值增大。