- 在线时间
- 1029 小时
- 最后登录
- 2017-4-30
- 注册时间
- 2014-1-21
- 听众数
- 213
- 收听数
- 2
- 能力
- 100 分
- 体力
- 15803 点
- 威望
- 98 点
- 阅读权限
- 150
- 积分
- 8600
- 相册
- 0
- 日志
- 0
- 记录
- 3
- 帖子
- 1549
- 主题
- 715
- 精华
- 5
- 分享
- 0
- 好友
- 542
TA的每日心情 | 开心 2017-4-28 17:18 |
---|
签到天数: 415 天 [LV.9]以坛为家II
 群组: 乐考无忧考研公益讲座 群组: 2017美赛两天强训 群组: 模友会交流视频 群组: 群组: 国赛讨论 |
1.数论算法 ! C" G+ L2 | B9 l- n
求两数的最大公约数
% A% p$ f$ V% R9 k1 t% ?' w- Sfunction gcd(a,b:integer):integer; 6 n1 e2 o8 {5 [
begin 5 k: b4 a; ~# y: } u& E% ?* D
if b=0 then gcd:=a
. [, G& k. D0 ~7 H; t! Z6 H# Telse gcd:=gcd (b,a mod b); 4 R3 G5 z8 p! ], o
end ;
7 Z- \+ P; A0 {2 y
- L/ w/ |' B4 J# [: J/ ~求两数的最小公倍数
; _. W0 m- W- o& Bfunction lcm(a,b:integer):integer;
0 v" ]0 E/ R: Y" q& n, s {/ Ybegin
% R- T( i* O* f8 {" \2 lif a< b then swap(a,b);
3 p- W4 e, @* N" L+ R+ w( {lcm:=a; ! Q) H3 _$ y f/ H! l$ [5 _
while lcm mod b >0 do inc(lcm,a);
# _& X r. [( Q0 ~% Bend; 6 _( c# o p. g- W9 a4 F7 k' E# B; P
" |; v+ Z0 l1 r* u( y7 L素数的求法 3 {! L. Q0 j6 p) |% ?
A.小范围内判断一个数是否为质数: ( }& C: ?! d( F1 _" V+ g. D# t
function prime (n: integer): Boolean; 1 e t2 R# c8 Y0 p3 j; Z
var I: integer;
" c3 F% T1 z! G' X; [( s$ \begin
* I# N. \$ ^! F+ K0 Tfor I:=2 to trunc(sqrt(n)) do
% g1 i: N- D: P- [( bif n mod I=0 then
7 ?: |! Y2 ]' ]2 pbegin
. p- u% a2 R7 }prime:=false; exit;
- W% g7 c$ I' \- l4 u+ s. Jend;
0 i. {; V- F$ N, w0 r7 \$ } ^6 k9 d4 xprime:=true; 4 }' `+ @7 X$ s* x
end;
" L4 }1 T4 y" a% b6 p+ w" I2 O
6 I* V1 G' e& `$ EB.判断longint范围内的数是否为素数(包含求50000以内的素数表):
! Q4 i- i" `8 Nprocedure getprime; ( `% v, c- M- ~" r, A& L9 C+ k0 y
var 3 I9 @8 k" \) E, k: n3 s, |$ Z& }
i,j:longint; * a; _, F( f3 W( s! h
p:array[1..50000] of boolean;
1 D4 {3 m& B8 |9 j7 Rbegin % H }9 [0 ?8 X% ^% O y% v
fillchar(p,sizeof(p),true); " ` D. Z8 d2 |0 j" e
p[1]:=false;
9 u. ?. T$ I# h3 G! M3 ]3 c1 C! [i:=2; ( T6 e. a0 U6 g! h7 b
while i< 50000 do 1 n. |! o% B! P, T# R3 c& _4 J
begin
+ F/ k0 i4 F% `9 Y- hif p then
r8 G; e4 g* J" Obegin # c9 z/ [# L ]/ t6 m5 }, F4 w
j:=i*2;
5 E" X, F7 Y* p' F- \6 {while j< 50000 do
6 k- i+ t" a( K" Tbegin % E* M: D5 y/ U0 F/ R
p[j]:=false;
, v. p+ R' Z: R" c% [0 e" [inc(j,i); : s! L, [% [9 i* S$ J
end;
% q' s6 s; h& V. S, m5 M. yend;
4 A* y) w! }$ Z& h1 Xinc(i);
C u/ l8 z4 o5 F) E" `end;
* W! ?0 N3 r8 t( Q8 v$ C) \6 ~l:=0; L8 q% _: ~& d! U0 [) ^
for i:=1 to 50000 do & Z) [0 P% K( b# J: Y* q
if p then 2 h* O1 b# a/ D& f, d$ l- ?; H$ y
begin
5 V+ T" B, K0 Rinc(l);
1 M ^, R( U- N4 F* v% j( }pr[l]:=i;
/ f0 u' h f" f0 rend; 5 Q. D& B2 b+ K: Q% V
end;{getprime}
! p2 z h1 X, }, n; P. p, y6 Dfunction prime(x:longint):integer;
% X% K9 A i9 {, D) hvar i:integer; : b% ?- h9 Z, a! A
begin % m G& \, B4 b' m
prime:=false; 5 M1 H( o* Q1 o3 w
for i:=1 to l do 8 x) I# |2 G/ E3 _ G7 U
if pr >=x then break
* I6 h; A5 o: O( `* a$ S1 V6 i" aelse if x mod pr=0 then exit;
* S& Q& J8 ~9 C' G Qprime:=true; 4 u) O2 _* B& m9 U: a+ b$ |# \
end;{prime}
+ g8 [0 D% H W1 F- ~
) Z8 }& V+ C) K7 {! M" H2. ' I* c8 p5 R1 i; N6 W
1 t- K* I4 K# N( @0 @
3. : X) g: b9 T5 l: j- K1 ?$ G6 j1 I/ q
- p# P: ~. O2 J3 e* P6 N* |4.求最小生成树
8 X, D; \8 | l6 u3 x* l- |A.Prim算法: . R9 g9 x: ?) W% r% o
procedure prim(v0:integer); : z1 A, i I: l) l2 D" o! }
var 5 y9 l8 W6 t. k3 v. g- {
lowcost,closest:array[1..maxn] of integer; 2 e$ r0 d% {# N2 n
i,j,k,min:integer; 4 _8 i' N9 b! Y4 X# q* \
begin
/ U8 d. u+ {# \for i:=1 to n do * f4 a+ ? W. i1 \- Y
begin
+ S# m8 y$ N7 a, K$ Zlowcost:=cost[v0,i]; ?! O6 e1 t d% v
closest:=v0; / U) f( m; k' @& g. @5 X8 W
end;
8 D# K; a; S2 k' T4 D! L6 hfor i:=1 to n-1 do
' }1 S! e3 T+ M+ d& d _ R& M; }# {begin & n! W! ?, N. T- g2 o! A
{寻找离生成树最近的未加入顶点k}
4 M; y5 i% R( W' {3 x: [3 umin:=maxlongint; * g# s# G$ D1 @
for j:=1 to n do
6 {2 }7 `; m. b6 ~( T% }: y2 L) wif (lowcost[j]< min) and (lowcost[j]< >0) then
( ]! [5 \$ }7 j" ^begin
4 m9 s7 z' Q! N$ U0 y4 g) I: K1 omin:=lowcost[j];
0 w! E7 I L# Z9 jk:=j; 1 }: [5 Z' A D4 X8 G/ ~
end;
9 z l* m- J! plowcost[k]:=0; {将顶点k加入生成树}
' `6 a7 i& k1 w3 E, r" R. l5 ]{生成树中增加一条新的边k到closest[k]}
0 N1 @. x5 f3 `0 P7 E( B. y{修正各点的lowcost和closest值}
& M/ _: O7 z" jfor j:=1 to n do
, n3 G9 R" y7 h# D: Y- c, Fif cost[k,j]< lwocost[j] then + D; T, g* c1 t% D0 `
begin ! F7 j# v9 q3 Y' S! I! _# M7 V
lowcost[j]:=cost[k,j];
, G8 o5 K9 X7 ~closest[j]:=k;
" f8 S2 }" |4 Tend;
9 F# U" r8 l' [ D- F' aend; / _- ^! B; F) W1 U2 k, B' M# L
end;{prim}
$ Z& e1 d7 w7 z; oB.Kruskal算法:(贪心) ! ]) B- Z- H- b4 P7 _
按权值递增顺序删去图中的边,若不形成回路则将此边加入最小生成树。
8 g Y2 K6 n; c- @9 Gfunction find(v:integer):integer; {返回顶点v所在的集合}
) F& z7 K) _+ K0 C0 ivar i:integer; 0 k8 r+ F/ D* T
begin $ N) b2 S1 T, ?" s5 e+ c
i:=1; & N( \: z- T+ Q3 j9 Z) r. y
while (i< =n) and (not v in vset) do inc(i); * s& r7 @! H+ X, d- b- w
if i< =n then find:=i
~8 A& X6 q8 m3 W; T1 A% h p' f0 helse find:=0;
: ?: x$ V& o* bend; 2 _0 d' j" u# Y/ a' d
procedure kruskal;
) m1 \+ y5 Y% E9 ?3 tvar
2 t' v) @4 p- V7 K. g7 mtot,i,j:integer; . ~; }8 J$ z# o3 k8 e
begin 0 d& T' S7 A6 i/ n9 O* _
for i:=1 to n do vset:=;{初始化定义n个集合,第I个集合包含一个元素I}
, |- N0 L: A3 b% X4 L9 q/ kp:=n-1; q:=1; tot:=0; {p为尚待加入的边数,q为边集指针}
4 s1 G( }* n& R/ z* ~sort;
$ l! q$ J7 O. } x{对所有边按权值递增排序,存于e[I]中,e[I].v1与e[I].v2为边I所连接的两个顶点的序号,e[I].len为第I条边的长度} ) ?. w+ I/ a1 u# ?) T# Q3 y
while p >0 do
; X Y$ p5 C& @# H {+ j( _. P0 Ebegin
+ {+ ]5 H3 S# H- @$ ~& o# Ji:=find(e[q].v1);j:=find(e[q].v2);
6 a. l8 [( U* a2 A2 b7 x: Oif i< >j then 2 c6 k6 r) h5 \. S9 P4 e. ^% A
begin
: t8 g' u t4 x9 Y3 @inc(tot,e[q].len); : w8 a+ l4 x0 F! [6 `$ e2 k: v
vset:=vset+vset[j];vset[j]:=[]; 0 E! o: g1 ?$ X: E; _
dec(p);
7 C1 I: w# ?3 c0 I/ Hend; ! h6 W( V [) v p
inc(q); 6 f+ l/ @; v9 F8 t
end; 1 O7 B! w- ]& z
writeln(tot);
7 P5 B1 S/ e/ _+ xend; * E9 M+ O. I, e, v, ?
9 F" s7 b% g' p% J0 \- l5.最短路径 5 ?/ R3 D& |, L0 V/ L5 h
A.标号法求解单源点最短路径: " A3 I K: G4 G
var . L& V# E; `( C5 g V
a:array[1..maxn,1..maxn] of integer; ) K1 O8 X5 t: @* ~; z; o
b:array[1..maxn] of integer; {b指顶点i到源点的最短路径}
4 E; X- O% ?2 s4 X& ?' T: r Kmark:array[1..maxn] of boolean; 3 V3 w8 O2 K1 i1 Z
8 L* ~! Z2 ?7 _" K+ R/ r
procedure bhf;
3 I' k/ x" b$ j5 yvar ' G# x# R$ z4 e4 M( L
best,best_j:integer; : f1 h3 c& ]2 g$ J2 ]$ x* G( X3 R
begin
. a& G0 ~6 B+ \, u" Zfillchar(mark,sizeof(mark),false);
& Y* k8 O$ R" J j2 @% Pmark[1]:=true; b[1]:=0;{1为源点} + \$ J1 A0 d# p! g8 \3 H
repeat
# V+ B, s8 u/ n4 [% j# Ybest:=0;
9 O8 c+ S3 E! @. Sfor i:=1 to n do # n$ P' H( O; n3 k" d( G: {% h
If mark then {对每一个已计算出最短路径的点} . Q) n5 }3 K% S6 R
for j:=1 to n do
9 u6 B. Y7 G0 I; C" H8 d1 hif (not mark[j]) and (a[i,j] >0) then Z+ X" `$ m* @1 M8 w1 o
if (best=0) or (b+a[i,j]< best) then # J& J7 D- K; `: C* X' \- d% ]8 T
begin 4 K$ z4 \0 g5 l' A
best:=b+a[i,j]; best_j:=j; 6 T- V& J- t$ c3 q
end; / x% `6 L+ {& X' Y
if best >0 then
' W m G. G% Ibegin
0 y* r( a& Z2 B1 ?5 |7 z+ gb[best_j]:=best;mark[best_j]:=true;
1 X7 Z4 Q4 E/ S; gend;
" P( }1 T1 N I) q; d, _7 buntil best=0; 8 Q6 T# z: `; {7 m5 W, L$ `
end;{bhf}
& [& a: w1 {; i$ r- ^
0 n3 ]' e' q$ S4 B9 O0 EB.Floyed算法求解所有顶点对之间的最短路径: t9 k' i( N# l! u; F) `
procedure floyed;
9 y9 O$ L" H* } u! Gbegin + z: t7 U6 U4 `; ^: n1 K) I. ^
for I:=1 to n do 5 v1 X2 V5 y2 U; v# j6 f. T) P
for j:=1 to n do 1 @5 }1 A4 R* |1 K0 ^3 L
if a[I,j] >0 then p[I,j]:=I else p[I,j]:=0;
! { U9 }# G2 v! X/ K$ }3 q{p[I,j]表示I到j的最短路径上j的前驱结点} 7 y0 T! K; X5 H+ }
for k:=1 to n do {枚举中间结点} ( z3 A6 F( Q9 b+ ~, m* N
for i:=1 to n do 9 T' \1 y2 D$ s# f- J; e. n
for j:=1 to n do
9 P8 ]5 b8 }0 I) C' t3 O# b1 [if a[i,k]+a[j,k]< a[i,j] then
. n* k8 J* `" `+ s0 I) n/ Nbegin
4 w! |/ p, b# z% t; g* a0 q: Ia[i,j]:=a[i,k]+a[k,j]; 0 f* q7 y; q- j# a/ j, t
p[I,j]:=p[k,j];
8 S8 |6 ~% z- [% {) iend;
" A/ s& t* H$ w2 l5 bend;
) K! N3 ?! T# bC. Dijkstra 算法:
. I. G: }% ^4 d, c% u8 F# T类似标号法,本质为贪心算法。
3 \& B: d+ J) Y( v( Y; Qvar
, L6 ~, T u' ^ K, Fa:array[1..maxn,1..maxn] of integer;
7 w8 H9 a, a; S7 P# wb,pre:array[1..maxn] of integer; {pre指最短路径上I的前驱结点} ! [, s- [. d: a, r
mark:array[1..maxn] of boolean;
4 t* N& P, E8 x. L: lprocedure dijkstra(v0:integer); 5 t) K0 u! n2 e
begin
8 D! t9 p; H) V4 G+ ~0 U5 Dfillchar(mark,sizeof(mark),false); & O7 E3 U% A4 a- k; q
for i:=1 to n do $ l- ]& Q6 `* m7 q% _. u6 o* |3 A& I& x
begin
9 L- H3 M0 g9 l0 xd:=a[v0,i];
& S( P$ s3 H8 ]% ?4 Vif d< >0 then pre:=v0 else pre:=0; : k) `* N7 W! Z7 U
end; 4 ^+ ~% c0 z6 e1 }+ E
mark[v0]:=true;
|% J: I* Y, h. k" lrepeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数}
5 p" a3 h; N, q7 J& M. qmin:=maxint; u:=0; {u记录离1集合最近的结点} 0 f/ g3 V U+ M. D1 N
for i:=1 to n do
( i" P: w# O' Q4 Vif (not mark) and (d< min) then & s9 x9 H1 j- F! X# p1 {- V+ B
begin
{ ?! ~7 e6 l( B' Eu:=i; min:=d;
+ @% H; X* E- \, U5 a. M: [end; , n% R- U# O% V
if u< >0 then + {* x3 d4 M: _3 V* Q. V4 d
begin
" Q+ D2 V# R# l% ~1 e$ Emark:=true;
( M A6 f' [$ B" h: g% Kfor i:=1 to n do
+ L. Z+ I5 ?4 ]$ [1 Oif (not mark) and (a[u,i]+d< d) then
0 {- w: }" b* |3 _8 t6 m2 U4 |begin
9 w/ e4 ?) d- @d:=a[u,i]+d;
) @5 ]( Z8 ^7 `9 Z# U/ [* Ypre:=u;
( A0 K! l# K$ F9 B3 Fend; * j+ C. [9 e6 i) t2 i. M
end;
0 ^/ t5 e' m3 p* D4 n. ountil u=0;
/ J+ s+ g* m9 L. N: uend;
. h5 ^9 h, W6 M3 N! Q/ ID.计算图的传递闭包 6 T& s; W2 X! |$ n- M3 U
Procedure Longlink;
5 |1 R) ]9 ]7 ?4 W: u) f9 OVar
0 k# t: D1 ]/ ?. @T:array[1..maxn,1..maxn] of boolean; : q* H! ^% {2 a4 ~1 G' A
Begin & e4 E7 A. d9 Q
Fillchar(t,sizeof(t),false);
3 S G+ Q: i) t z! ^/ E9 Y$ QFor k:=1 to n do * l3 H& T! O9 j% s7 S
For I:=1 to n do , y; O3 o) @- U9 P# K, F4 y
For j:=1 to n do + S2 e# \9 B- t7 ]
T[I,j]:=t[I,j] or (t[I,k] and t[k,j]); % A4 Q- @) s. x" L: J* e
End;
5 P) I0 A: o: G9 u' z% f9 C1 H. d6 m t5 Z7 U
|
zan
|