1.数论算法
2 X5 ?9 j+ Q6 Q) Z3 N5 D r求两数的最大公约数- h3 |8 F* i' `8 U$ A* `, B- f
function gcd(a,b:integer):integer;
% a% e! w+ O! j+ B, Kbegin) u( q" \" J% B4 _( I u6 G9 k: L
if b=0 then gcd:=a
/ E6 S% g! ~6 X3 Aelse gcd:=gcd (b,a mod b);
1 H& N; Z$ m4 Z' Q6 @! w3 tend ;0 ]5 J# d' F/ J. X/ e6 F" e$ {: R
1 o: |9 C0 H; s E2 y, S( @ U; ~
求两数的最小公倍数
$ n3 O# _$ q( v# j5 c2 b( A! {function lcm(a,b:integer):integer;( f2 I7 {1 V9 Z6 W
begin. T& G: }" N0 h7 u. Q l, V, c/ K
if a< b then swap(a,b);
" e+ y. t0 `( Elcm:=a;5 s: `& N; Z% Z' @1 p d1 {
while lcm mod b >0 do inc(lcm,a);9 P& }% H" g- ?4 c' {
end;
6 I8 Q. `; M3 D+ |& h+ u. M' O/ p8 g2 u9 A( J
素数的求法
5 _3 S- F) v. F, ?' w+ ]2 aA.小范围内判断一个数是否为质数:: J0 W8 p& F: u; S% d
function prime (n: integer): Boolean;
, C8 X- q0 k2 Y7 M5 bvar I: integer;
2 a8 H% u# e3 q: i( ?+ P7 Ebegin
' `! s& y0 C, Cfor I:=2 to trunc(sqrt(n)) do6 O& N. n* B1 y
if n mod I=0 then
. E k, }/ w% o% g3 L2 cbegin6 ?8 A! I O4 U1 ^: n
prime:=false; exit;$ B: e0 R! p1 y# o! G& i8 S
end;' r% o- G$ m9 {% M
prime:=true;- Y: e/ C t7 |* O
end;
# l1 K( k: A% L4 e+ a" a v$ ]1 B$ b
B.判断longint范围内的数是否为素数(包含求50000以内的素数表):
" E, w# w! ]& @6 Z/ ?* h) Wprocedure getprime;
2 p o7 s0 |. t, F( o6 w2 uvar
5 [+ x3 W: C, A( z" V b2 b6 Mi,j:longint;
0 M5 _$ [5 I# s# R. W3 Gp:array[1..50000] of boolean;
/ F8 c: H" ? K" `begin* u, A9 ?. S8 n
fillchar(p,sizeof(p),true);
$ G8 A/ V# ^9 W) ^# i# Yp[1]:=false;
$ d( p" b4 ~7 q8 X Ti:=2;C5 }$ G5 b5 Q4 z' V7 |5 a# N8 s
while i< 50000 do
; q' `$ \5 K+ Tbegin
) J4 `5 C9 p; Y' r0 r @, ^* a" Bif p then
- J; ~ a f/ b: pbegin; R9 W$ |7 A1 W4 m4 h. v- S2 ^
j:=i*2;
% ^ \% T* K8 B" z" w" Y, @while j< 50000 do4 m; u8 D q6 j3 U: \. a/ {
begin# H/ t! w, G8 n: x5 h+ i" l
p[j]:=false;
/ w' h8 U. l6 p- @& ]inc(j,i);
' R- h; d! c9 h, W/ A: w: hend;% j [) C% l- @
end;6 J/ M- m7 L1 M8 P$ ?
inc(i);
/ Z1 i, `- G5 d: i3 K& Jend;+ @$ Q9 u9 S8 X l" h8 M2 H
l:=0;
i" P9 {: c* s3 j8 d! Xfor i:=1 to 50000 do9 E( N2 j# _3 r1 L
if p then
9 o# ?1 u- l' J Qbegin( f5 F. B% h6 i# I
inc(l);; J7 k. ^$ b( c9 p% Z% ]- d
pr[l]:=i;( k( q( \( U }0 A b1 F% J
end;
4 W, o; k. G$ G0 F: Qend;{getprime}
3 l# V& T% B* V# L* f+ W& }0 Jfunction prime(x:longint):integer;
2 [& l. ?. y9 }/ pvar i:integer;0 V. D: E, A0 `5 C0 a
begin* y. w! E* f4 n6 C- I2 T
prime:=false;& `+ d4 D! B) F
for i:=1 to l do* r* z9 c0 |; M1 `) G+ e% f# p
if pr >=x then break
4 x# ?. J/ z$ D, A6 I/ `% J4 aelse if x mod pr=0 then exit;, F) w0 l3 o3 E$ A' i9 S7 a: J
prime:=true;
9 l8 ~) z8 m4 o. M" Pend;{prime}
% q5 @8 Z. z7 o
1 u7 G% I, k2 T8 Q5 L5 M1 p8 z2.
5 ~2 V) }9 s3 Z; t# u* N. f* j% J
3.
" f) n) [7 {9 B" n, J6 @% g- B( w* p/ D6 Z- u2 O% x
4.求最小生成树6 Q7 B& H4 i: I8 n* R$ g& ]/ A( F
A.Prim算法:0 ?% Y3 o' p( C- R
procedure prim(v0:integer);, v( F0 e8 I; O+ Q3 r! m; H' \+ W
var. X' b9 z* I0 q
lowcost,closest:array[1..maxn] of integer;
/ ]: ]2 N! J+ Ri,j,k,min:integer;9 i; S/ C5 S: q/ K& g" `: X9 }" ]
begin
% G7 U0 c; W& {7 I, v1 yfor i:=1 to n do
: f% K" Y) f/ h1 Gbegin5 [% W8 B: A; B, z% X% x' n
lowcost:=cost[v0,i];
( D" U3 L* Z8 U* G- m& E+ y5 kclosest:=v0;. l! m. n2 S" Z8 e7 \
end;- h, t4 k2 R+ E4 J
for i:=1 to n-1 do
' C8 |# N# C# P/ f ebegin
6 J, c+ u6 x' n! ]7 N, n D- Y5 Y; _! b{寻找离生成树最近的未加入顶点k}0 f! z" Q+ E8 D" u# A' K3 }- \9 u
min:=maxlongint;' {1 t# U9 f) e" M" T
for j:=1 to n do' b5 v0 Y1 i9 [' t
if (lowcost[j]< min) and (lowcost[j]< >0) then$ B& l: J M$ U+ {7 W
begin: k, I0 t: ]5 a( j6 V
min:=lowcost[j];
w8 G. c4 m1 z: H5 ck:=j;
9 t R. k5 r1 V3 T5 Q: j/ {, w% q; Send;5 B1 h) k3 V) v) |- S6 i2 e! k0 W
lowcost[k]:=0; {将顶点k加入生成树}( p, u$ Q) h' X x" }8 {4 [
{生成树中增加一条新的边k到closest[k]}3 T* v9 }5 t7 h( U8 M% Z( l) |5 |. G
{修正各点的lowcost和closest值}& e) g$ U, X# b' N0 Y z
for j:=1 to n do2 p( A' g( [ b8 C, Z8 U8 q' Z) E
if cost[k,j]< lwocost[j] then
! h3 I1 \" a+ Y8 Wbegin8 E8 p: z2 Q% Y* O) `
lowcost[j]:=cost[k,j];7 T" ^1 g3 m; Y% w& K
closest[j]:=k;
( ^) E2 Y' G4 {, G! o, a- E; zend;2 j" N/ h: `: A' \
end;
$ a6 _6 N4 @1 f) g2 I A& _) d# _2 Vend;{prim}
- }0 G7 ?4 U" m) o4 aB.Kruskal算法:(贪心)) o* i; F* x; q3 S
按权值递增顺序删去图中的边,若不形成回路则将此边加入最小生成树。
' y) `! ~( i/ Z- |function find(v:integer):integer; {返回顶点v所在的集合}' K) f" ?+ C d. V& C/ O0 Q
var i:integer;
1 w9 Q" e, n# p sbegin/ V& P; d9 C6 n5 S" W
i:=1;
2 d6 {- \5 ]) ^$ Z% J: n( V$ Twhile (i< =n) and (not v in vset) do inc(i);
& l% W* M4 T5 \2 `3 zif i< =n then find:=i
% x8 h, s, t% ?' ?1 R/ b7 P# Velse find:=0;
& R ]; \7 A0 z/ v6 }end;
, \3 D' O. e4 H) X S- W' Yprocedure kruskal;
; t e% [1 X* U9 X7 hvar5 D) y; L( m4 _ N8 z# W2 I: e
tot,i,j:integer;2 l; h! Z0 V' ^, h# i
begin% F$ R) {2 s4 K3 V2 S- }
for i:=1 to n do vset:=;{初始化定义n个集合,第I个集合包含一个元素I}, f/ r! ^5 s. |$ g
p:=n-1; q:=1; tot:=0; {p为尚待加入的边数,q为边集指针}
! ?, {4 W+ a+ Wsort;7 V7 \; s# X+ I3 X* Y1 G/ J
{对所有边按权值递增排序,存于e[I]中,e[I].v1与e[I].v2为边I所连接的两个顶点的序号,e[I].len为第I条边的长度}
/ D# S: W: k8 v% r! Mwhile p >0 do
$ ~, ~* O" l! h# u1 u ?( n" Pbegin; _* t( M0 G' e! m$ D8 V
i:=find(e[q].v1);j:=find(e[q].v2);7 | a9 m0 h; N0 H
if i< >j then
1 c0 l- V3 u" ubegin8 {& m% C) z8 z7 E3 o
inc(tot,e[q].len);
. z8 i* j- X- l# s9 D @: j/ Avset:=vset+vset[j];vset[j]:=[];
* m" ^0 Y- }# @$ ^7 rdec(p);
7 v, [- @' h, gend;' Z6 Q7 o# b+ j( p
inc(q);
5 i" I: [+ z# j {end;t; F* e% ~9 T& H. o% h
writeln(tot);8 Q9 @5 e& f* s% r. Y0 _
end;& k% n2 ?2 q5 k4 |3 Z! L% J
6 `7 p# T: q0 d/ q+ E! n8 m5.最短路径$ S5 P# b/ N# [& G
A.标号法求解单源点最短路径:. g ^) U1 v- l
var$ n( o$ P" r: l" S
a:array[1..maxn,1..maxn] of integer;\# } |5 q5 u5 @1 `! A$ d
b:array[1..maxn] of integer; {b指顶点i到源点的最短路径}
6 l% ~0 o* K; U) s' T: `: n. Amark:array[1..maxn] of boolean;
% Q7 r' W$ ^9 u/ w
; \# I9 f n9 U& _7 R" d% w0 tprocedure bhf;! N0 Q( B z( C' V6 f
var% N; ?( r6 }; x' u* T
best,best_j:integer;
7 M; j J8 E; U% r/ Kbegin# N5 v; {% Y7 I0 m! A
fillchar(mark,sizeof(mark),false);
. x: c( T1 m$ Wmark[1]:=true; b[1]:=0;{1为源点}- V5 f I( z2 ~4 b* V9 L) X
repeat# M$ i) i9 P! s
best:=0;8 s3 R V: h. `8 P4 ?3 V7 S. `
for i:=1 to n do
# M: M8 U7 x& m/ n& G, j8 [* T; nIf mark then {对每一个已计算出最短路径的点}
7 i$ T6 `) o' D" T$ {0 u/ nfor j:=1 to n do
; F$ J4 P2 l# G- [& M i( `if (not mark[j]) and (a[i,j] >0) then
% v& Y1 |+ W0 j6 j4 R$ c) Gif (best=0) or (b+a[i,j]< best) then
# ~( h _. E' {* X8 Wbegin
( \ E3 q5 w& p1 \! |5 Jbest:=b+a[i,j]; best_j:=j;6 H$ H$ W; [1 O% g2 f M
end;* q% \' o6 C3 W, Y( e2 W( }' D
if best >0 then
1 P2 y9 ^; R: m3 V7 qbegin4 N) _. h$ Z9 h
b[best_j]:=best;mark[best_j]:=true;6 t' u( f2 A$ A0 |9 ?9 n& U
end;
' m5 I6 \ l# E/ l1 `+ guntil best=0;
7 V7 z, `. v# J1 oend;{bhf}
5 i6 i* X1 N+ |7 q# l3 }8 m
. B! O8 p8 y: b* U2 w3 o. OB.Floyed算法求解所有顶点对之间的最短路径:" ]' n2 M! p$ n6 w
procedure floyed;
7 _# y. T; X& Z" Dbegin2 i5 @3 D" o. \3 V7 r6 D
for I:=1 to n do
! H5 U: k* m0 P! U. nfor j:=1 to n do
/ F3 `, `. k6 u0 Fif a[I,j] >0 then p[I,j]:=I else p[I,j]:=0;
) V, ~$ x9 d( C! R* w{p[I,j]表示I到j的最短路径上j的前驱结点}- l5 L0 k/ F3 I( i7 G8 I: I
for k:=1 to n do {枚举中间结点}6 v' L. w- }, B* n) [+ b0 K3 H
for i:=1 to n do
0 G+ z% ]# X, L# A9 ffor j:=1 to n do1 u6 c3 y( O$ D& E, d0 X* C
if a[i,k]+a[j,k]< a[i,j] then# v# m2 f% u& q9 {2 n7 v
begin* ~# z$ L- r1 ~# [, j( P
a[i,j]:=a[i,k]+a[k,j];
1 @' f$ h2 R0 ?0 P( Kp[I,j]:=p[k,j];
& \. ]( ]# R5 m$ `0 x8 V y2 Fend;7 t1 e$ B" t1 I' L: V& {- U3 g
end;1 h4 G1 x6 Z' N& Y
C. Dijkstra 算法:
. m: J- o; J! P5 S1 F7 i类似标号法,本质为贪心算法。
( E% s9 t8 r, ?& o2 T( Hvar
5 W0 I! M; M8 L$ v$ |4 Ja:array[1..maxn,1..maxn] of integer;
& Z; ^7 X. h: M7 Z4 B% bb,pre:array[1..maxn] of integer; {pre指最短路径上I的前驱结点}
# B% [& t8 ^6 H* G k2 Dmark:array[1..maxn] of boolean;
- Z. Z- K0 X1 A$ r/ L$ Gprocedure dijkstra(v0:integer);
& _# ]% {3 C! B! Y- o3 Y8 [$ y# ?begin) w1 d( H4 o, d3 n% Q% C( n+ |
fillchar(mark,sizeof(mark),false);/ v7 f. n* x* Y. f9 g. l
for i:=1 to n do4 T- K: s" j7 y) u! P
begin: d6 p0 _/ x8 x9 I4 f
d:=a[v0,i];7 J6 x" Y) z; W }+ P( Y5 s* ]1 T
if d< >0 then pre:=v0 else pre:=0;
% \6 r, v& y1 W3 Mend;& B" o- @0 Y' X( ~
mark[v0]:=true;! A1 g& g, M1 r: u6 }
repeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数}# O4 D$ f, `- ?6 N2 q" j, t
min:=maxint; u:=0; {u记录离1集合最近的结点}
) n+ ^4 h5 W' c, [" T+ f- ?for i:=1 to n do. E$ G' a) D L
if (not mark) and (d< min) then5 [# x- j9 Z' ?. v. g% G( a; m
begin6 t0 e9 }8 q$ s$ o
u:=i; min:=d;6 M4 K4 ^5 I& J3 @" _
end;
7 x0 V; Z2 ^, A% t, Aif u< >0 then. t) v- c+ \* P7 W
begin" m7 q; q X F3 C5 T
mark:=true;4 o' t$ C0 T) h* `+ L
for i:=1 to n do
( P1 n" B: r" t' f5 K9 |if (not mark) and (a[u,i]+d< d) then+ u6 \4 e: q0 ~$ E) X' F1 |. f
begin
- B! Y! V* N( J( {9 M2 @7 Q) U5 Nd:=a[u,i]+d;) ~. H1 n' i; w' i6 O0 n* S5 R
pre:=u;
# u# h, F# x0 i' W% g( ~& G, e2 g6 fend;
% z: ` T0 D3 y& E% ]end;
9 j0 I9 p. m) a% |7 |" ?. Huntil u=0;1 ?% j3 E5 T, o. v1 t# N* P% p( F" v
end;
1 `5 T. m$ i$ R3 C8 KD.计算图的传递闭包
( g7 h B7 Q2 r8 WProcedure Longlink;: Q0 H7 P4 m- ?5 [
Var4 m4 S. Z3 O) W9 f. t+ {" o+ Z
T:array[1..maxn,1..maxn] of boolean;1 \3 X* T8 _) u, V" o0 `
Begin
- j( v( p% h0 u! ?# c# E* iFillchar(t,sizeof(t),false);8 {/ L5 Q8 N0 ~: d
For k:=1 to n doZ; m% ?, u3 V$ U* v
For I:=1 to n do
7 L% o: i+ p, vFor j:=1 to n do
! d, g2 r- K- ^6 c$ q9 ?5 kT[I,j]:=t[I,j] or (t[I,k] and t[k,j]);
% a7 n1 q/ U1 |5 ]* H+ ?% }End;5 t) }3 ^1 y) R6 b2 t* p
/ e0 U8 }) M4 O( t3 \5 V