1、一、数论算法 1求两数的最大公约数 function gcd(a,b:integer):integer;begin if b=0 then gcd:=aelse gcd:=gcd (b,a mod b);end ; 2求两数的最小公倍数 function lcm(a,b:integer):integer;beginif a0 do inc(lcm,a);end; 3素数的求法 A.小范围内判断一个数是否为质数:function prime (n: integer): Boolean;var I: integer;beginfor I:=2 to trunc(sqrt(n) doif n mod
2、 I=0 then begin prime:=false; exit;end;prime:=true;end; B.判断 longint 范围内的数是否为素数(包含求 50000 以内的素数表):procedure getprime;var i,j:longint;p:array150000 of boolean;beginfillchar(p,sizeof(p),true);p1:=false;i:=2;while i=x then breakelse if x mod pri=0 then exit;prime:=true;end;prime 二、图论算法 1最小生成树 A.Prim 算法
3、:procedure prim(v0:integer);varlowcost,closest:array1maxn of integer;i,j,k,min:integer;beginfor i:=1 to n do beginlowcosti:=costv0,i;closesti:=v0;end;for i:=1 to n-1 do begin寻找离生成树最近的未加入顶点 kmin:=maxlongint;for j:=1 to n doif (lowcostj0) then beginmin:=lowcostj;k:=j;end;lowcostk:=0; 将顶点 k 加入生成树生成树中增加
4、一条新的边 k 到 closestk修正各点的 lowcost 和 closest 值for j:=1 to n doif costk,j0 do begini:=find(eq.v1);j:=find(eq.v2);if i0) then if (best=0) or (bi+ai,j0 then beginbbest_j:=best;markbest_j:=true;end;until best=0;end;bhf B.Floyed 算法求解所有顶点对之间的最短路径:procedure floyed;beginfor I:=1 to n dofor j:=1 to n doif aI,j0
5、 then pI,j:=I else pI,j:=0; pI,j表示 I 到 j 的最短路径上 j 的前驱结点 for k:=1 to n do 枚举中间结点for i:=1 to n dofor j:=1 to n doif ai,k+aj,k0 then prei:=v0 else prei:=0;end;markv0:=true;repeat 每循环一次加入一个离 1 集合最近的结点并调整其他结点的参数min:=maxint; u:=0; u 记录离 1 集合最近的结点 for i:=1 to n doif (not marki) and (di0 then beginmarku:=tr
6、ue; for i:=1 to n doif (not marki) and (au,i+du表示,则 EeI = Vej;d. 边活动最晚开始时间 ElI, 若边 I 由 表示,则 ElI = Vlk wj,k;若 Eej = Elj ,则活动 j 为关键活动,由关键活动组成的路径为关键路径。求解方法:a. 从源点起 topsort,判断是否有回路并计算 Ve;b. 从汇点起 topsort,求 Vl;c. 算 Ee 和 El; 6拓扑排序 找入度为 0 的点,删去与其相连的所有边,不断重复这一过程。例 寻找一数列,其中任意连续 p 项之和为正,任意 q 项之和为负,若不存在则输出 NO.
7、7.回路问题 Euler 回路(DFS)定义:经过图的每条边仅一次的回路。(充要条件:图连同且无奇点) Hamilton 回路定义:经过图的每个顶点仅一次的回路。 一笔画充要条件:图连通且奇点个数为 0 个或 2 个。 9判断图中是否有负权回路 Bellman-ford 算法 xI,yI,tI分别表示第 I 条边的起点,终点和权。共 n 个结点和m 条边。procedure bellman-fordbeginfor I:=0 to n-1 do dI:=+infinitive;d0:=0;for I:=1 to n-1 dofor j:=1 to m do 枚举每一条边if dxj+tj=be
8、st then exit; sn为前 n 个物品的重量和if kwk then search(k+1,v-wk);search(k+1,v);end;end; l DPFI,j为前 i 个物品中选择若干个放入使其体积正好为 j 的标志,为布尔型。实现:将最优化问题转化为判定性问题f I, j = f i-1, j-wi (wI0 thenif j+now=0 ThenBegint:=problemj.point+fi-problemj.time;If tfi Then fi:=t;End;Writeln(fM);End. C.求恰好装满的情况数。Ahoi2001 Problem2求自然数 n
9、本质不同的质数和的表达式的数目。思路一,生成每个质数的系数的排列,在一一测试,这是通法。procedure try(dep:integer);var i,j:integer;begincal; 此过程计算当前系数的计算结果,now 为结果if nown then exit; 剪枝if dep=l+1 then begin 生成所有系数cal;if now=n then inc(tot);exit;end;for i:=0 to n div prdep do beginxsdep:=i;try(dep+1);xsdep:=0;end;end; 思路二,递归搜索效率较高procedure try(
10、dep,rest:integer);var i,j,x:integer;beginif (rest0 thenfor k:=1 to n div now doif j+now*kmid do dec(j);在右半部分寻找比中间数小的数 if ij;if laj then swap(ai,aj);end; D. 冒泡排序procedure bubble_sort;var i,j,k:integer;beginfor i:=1 to n-1 dofor j:=n downto i+1 doif ajr) or (air then beginq:=(p+r-1) div 2;merge_sort (
11、a,p,q);merge_sort (a,q+1,r);merge (a,p,q,r);end;end;mainbeginmerge_sort(a,1,n);end. G.基数排序思想:对每个元素按从低位到高位对每一位进行一次排序 五、高精度计算 高精度数的定义:typehp=array1maxlen of integer; 1高精度加法 procedure plus ( a,b:hp; var c:hp);var i,len:integer;beginfillchar(c,sizeof(c),0);if a0b0 then len:=a0 else len:=b0;for i:=1 to l
12、en do begininc(ci,ai+bi);if ci10 then begin dec(ci,10); inc(ci+1); end; 进位end;if clen+10 then inc(len);c0:=len;end;plus 2高精度减法procedure substract(a,b:hp;var c:hp); var i,len:integer;beginfillchar(c,sizeof(c),0);if a0b0 then len:=a0 else len:=b0;for i:=1 to len do begininc(ci,ai-bi);if ci1) and (clen
13、=0) do dec(len);c0:=len;end; 3高精度乘以低精度 procedure multiply(a:hp;b:longint;var c:hp);var i,len:integer;beginfillchar(c,sizeof(c),0);len:=a0;for i:=1 to len do begininc(ci,ai*b);inc(ci+1,(ai*b) div 10);ci:=ci mod 10;end;inc(len);while (clen=10) do begin 处理最高位的进位clen+1:=clen div 10;clen:=clen mod 10;inc
14、(len);end;while (len1) and (clen=0) do dec(len); 若不需进位则调整 lenc0:=len;end;multiply 4高精度乘以高精度 procedure high_multiply(a,b:hp; var c:hpvar i,j,len:integer;beginfillchar(c,sizeof(c),0);for i:=1 to a0 dofor j:=1 to b0 do begininc(ci+j-1,ai*bj);inc(ci+j,ci+j-1 div 10);ci+j-1:=ci+j-1 mod 10;end;len:=a0+b0+
15、1;while (len1) and (clen=0) do dec(len);c0:=len;end; 5高精度除以低精度 procedure devide(a:hp;b:longint; var c:hp; var d:longint);c:=a div b; d:= a mod bvar i,len:integer;beginfillchar(c,sizeof(c),0);len:=a0; d:=0;for i:=len downto 1 do begind:=d*10+ai;ci:=d div b;d:=d mod b;end;while (len1) and (clen=0) the
16、n dec(len);c0:=len;end; 6高精度除以高精度 procedure high_devide(a,b:hp; var c,d:hp);vari,len:integer;beginfillchar(c,sizeof(c),0);fillchar(d,sizeof(d),0);len:=a0;d0:=1;for i:=len downto 1 do beginmultiply(d,10,d);d1:=ai;while(compare(d,b)=0) do 即 d=bbeginSubtract(d,b,d);inc(ci);end;end;while(len1)and(c.slen
17、=0) do dec(len);c.len:=len;end; 六、 树的遍历 1已知前序中序求后序 procedure Solve(pre,mid:string);var i:integer;beginif (pre=) or (mid=) then exit;i:=pos(pre1,mid);solve(copy(pre,2,i),copy(mid,1,i-1);solve(copy(pre,i+1,length(pre)-i),copy(mid,i+1,length(mid)-i);post:=post+pre1; 加上根,递归结束后 post 即为后序遍历end; 2已知中序后序求前序
18、 procedure Solve(mid,post:string);var i:integer;beginif (mid=) or (post=) then exit;i:=pos(postlength(post),mid);pre:=pre+postlength(post); 加上根,递归结束后 pre 即为前序遍历solve(copy(mid,1,I-1),copy(post,1,I-1);solve(copy(mid,I+1,length(mid)-I),copy(post,I,length(post)-i);end; 3已知前序后序求中序的一种 function ok(s1,s2:st
19、ring):boolean;var i,l:integer; p:boolean;beginok:=true;l:=length(s1);for i:=1 to l do beginp:=false;for j:=1 to l doif s1i=s2j then p:=true;if not p then begin ok:=false;exit;end;end;end; procedure solve(pre,post:string);var i:integer;beginif (pre=) or (post=) then exit;i:=0;repeatinc(i);until ok(co
20、py(pre,2,i),copy(post,1,i);solve(copy(pre,2,i),copy(post,1,i);midstr:=midstr+pre1;solve(copy(pre,i+2,length(pre)-i-1),copy(post,i+1,length(post)-i-1);end; 七 进制转换 1.任意正整数进制间的互化 除 n 取余 2.实数任意正整数进制间的互化乘 n 取整 3.负数进制:设计一个程序,读入一个十进制数的基数和一个负进制数的基数,并将此十进制数转换为此负 进制下的数:-R-2,-3,-4,-20 八 全排列与组合的生成 1.排列的生成:(1n )
21、procedure solve(dep:integer);vari:integer;beginif dep=n+1 then begin writeln(s);exit; end;for i:=1 to n doif not usedi then begins:=s+chr(i+ord(0);usedi:=true;solve(dep+1);s:=copy(s,1,length(s)-1); usedi:=false;end;end; 2.组合的生成(1n 中选取 k 个数的所有方案)procedure solve(dep,pre:integer);vari:integer;beginif d
22、ep=k+1 then begin writeln(s);exit; end;for i:=1 to n doif (not usedi) and (ipre) then begins:=s+chr(i+ord(0);usedi:=true;solve(dep+1,i);s:=copy(s,1,length(s)-1); usedi:=false;end;end; 九.查找算法 1.折半查找 function binsearch(k:keytype):integer;var low,hig,mid:integer;beginlow:=1;hig:=n;mid:=(low+hig) div 2;
23、while (amid.keyhig then mid:=0;binsearch:=mid;end; 2.树形查找 二叉排序树:每个结点的值都大于其左子树任一结点的值而小于其右子树任一结点的值。查找function treesrh(k:keytype):pointer;var q:pointer;beginq:=root;while (qk) doif kgoal then begin 若未移到目标 Move(k-1,6-now-goal); 剩下的先移到没用的柱上Writeln(k moved from now to goal);Hgoal,hgoal,0+1:=hnow,nowp; hno
24、w,nowp:=0;Inc(hgoal,0); dec(hnow,0);Move(k-1,goal); 剩下的移到目标上End; 十二、DFS 框架 NOIP2001 数的划分 procedure work(dep,pre,s:longint); 入口为 work(1,1,n)dep 为当前试放的第 dep 个数,pre 为前一次试放的数,s 为当前剩余可分的总数var j:longint;begin if dep=n then begin if s=pre then inc(r); exit; end; for j:=pre to s div 2 do work(dep+1,j,s-j);
25、end;类似:procedure try(dep:integer);var i:integer;beginif dep=k then beginif tot=adep-1 then inc(sum);exit; end;for i:=adep-1 to tot div 2 do beginadep:=i; dec(tot,i); try(dep+1);inc(tot,i);end;end;try 十三、BFS 框架 IOI94 房间问题head:=1; tail:=0;while tail=1) and (I=L.len) then while jI do begin p:=p.next; i
26、nc(j); end;loc:=p;end; 2单链表的插入操作 procedure insert(L:linklist; I:integer; x:datatype);var p,q:pointer;beginp:=loc(L,I);new(q);q.data:=x;q.next:=p.next;p.next:=q;inc(L.len);end; 3单链表的删除操作 procedure delete(L:linklist; I:integer);var p,q:pointer;beginp:=loc(L,I-1);q:=p.next;p.next:=q.next;dispose(q);dec(L.len);end; 4双链表的插入操作(插入新结点 q) p:=loc(L,I);new(q);q.data:=x;q.pre:=p;q.next:=p.next;p.next:=q;q.next.pre:=q; 5双链表的删除操作 p:=loc(L,I); p 为要删除的结点p.pre.next:=p.next;p.next.pre:=p.pre;dispose(p);