- 在线时间
- 1029 小时
- 最后登录
- 2017-4-30
- 注册时间
- 2014-1-21
- 听众数
- 213
- 收听数
- 2
- 能力
- 100 分
- 体力
- 15807 点
- 威望
- 98 点
- 阅读权限
- 150
- 积分
- 8571
- 相册
- 0
- 日志
- 0
- 记录
- 3
- 帖子
- 1549
- 主题
- 715
- 精华
- 2
- 分享
- 0
- 好友
- 542
TA的每日心情 | 开心 2017-4-28 17:18 |
|---|
签到天数: 415 天 [LV.9]以坛为家II
 群组: 乐考无忧考研公益讲座 群组: 2017美赛两天强训 群组: 模友会交流视频 群组: 群组: 国赛讨论 |
1.数论算法
9 @( _, S- ?3 c! M" K1 {# D求两数的最大公约数
5 R0 S2 R7 A* w; E8 U; p: K/ |function gcd(a,b:integer):integer; $ V7 K& y y' c5 D5 B
begin
" X) q+ f$ K" O: H( Fif b=0 then gcd:=a
4 W7 H5 x9 p. _) O- N/ r+ J$ felse gcd:=gcd (b,a mod b); 2 s! L4 Z5 k' k) C6 r4 \1 r/ y
end ;
2 @6 X: K$ N5 l( @7 \( h
# }! U3 g: [2 @2 ^/ K9 w求两数的最小公倍数 ! X# R* @7 z0 f! ~8 e# K4 M) W
function lcm(a,b:integer):integer;
# l$ v2 B7 N! w: d$ ?! H) @begin ' D8 @9 D5 d2 f2 ^! L& X2 S* [( \
if a< b then swap(a,b); 3 p2 s6 X j$ ^& A
lcm:=a; - {7 W# _$ G4 O7 \! J+ |
while lcm mod b >0 do inc(lcm,a); " E7 s2 {5 g) q# O- d
end; 8 Z2 I) i5 d+ O" X
) K- v h0 P8 d9 P; f% C' U, `
素数的求法
5 _3 S6 c/ _' ?" FA.小范围内判断一个数是否为质数: t* {2 J4 g, g4 z, J6 S, @1 L1 X
function prime (n: integer): Boolean; : L* Y# A; S7 y- k" q# G
var I: integer; 7 S# i# \, f9 u. r* U* T, ^, s7 k
begin
6 L" }. q% [' D# [2 lfor I:=2 to trunc(sqrt(n)) do
Z8 F- s5 \5 v5 Uif n mod I=0 then 8 D" }) T8 b$ Z4 K- H: o( k# o
begin
1 ~' _4 e* s' b) b( W& C( Yprime:=false; exit;
; q% q4 C; ]# i- G/ Oend;
: i2 K5 b0 v% h. Uprime:=true;
/ U; }, X" X, G5 _9 Y) [end;
k/ F% P' F% t; K! \3 e1 d2 X3 f8 J0 n3 _' D
B.判断longint范围内的数是否为素数(包含求50000以内的素数表):
% e; Q5 K d% ^5 n3 R. a4 Dprocedure getprime; ( N, z, I) Z2 T
var 3 q6 [) J* m( k& ?2 i! j5 P
i,j:longint;
3 a2 ?7 B+ F* O* Gp:array[1..50000] of boolean;
$ O* n' r, b. d5 ?0 Z+ }4 Nbegin
: [* L* q5 i& p( I; q$ o' Vfillchar(p,sizeof(p),true);
8 _+ W/ h2 ~) T, }; z' c0 Kp[1]:=false;
4 @/ R2 L* b7 Ti:=2;
1 e9 ]% s. V ^3 b$ [while i< 50000 do c* s# i6 r$ K; B, E) v8 P
begin
& O- v- r1 ?0 U) }" L0 O+ |% ~if p then
' K. D: n! m6 U+ [0 ]3 q3 G( Ebegin , Y4 A$ F, ^: r) o2 N9 L
j:=i*2; 0 T" r! r& W7 @! T
while j< 50000 do
/ ?' G; y1 j: k$ p; F+ Hbegin 5 n) U, d$ w' C2 p: ]4 j7 R6 @
p[j]:=false;
1 F$ k" _% Z$ ^2 f4 m7 L1 Finc(j,i);
' R* E- R4 F# Y, [; Eend;
, R4 H9 r1 s* m$ mend; + z6 s4 c) ~, |8 ~) r2 B
inc(i);
7 q2 f/ W. D; t5 l+ eend;
: Z, p; |) ]& \7 H2 C! _% `l:=0; 7 A. l; b5 i* T& t; b
for i:=1 to 50000 do 0 }. b( I4 b0 W( _' {- G* ?/ R" C
if p then
2 Q# J' k1 y9 O# w! g& Y; r7 z; xbegin
9 S4 J0 I8 n% t7 N) Jinc(l);
; ]- t2 m# I$ _! P8 z3 T: ]pr[l]:=i; 9 V; w% p2 M" \
end;
`- I" [* r w5 R- D0 send;{getprime} 9 |4 B7 c) ]. j8 c9 e- E
function prime(x:longint):integer; - |0 z2 p7 X* \: R! z
var i:integer; ! }9 K) W- |& Z1 g( N
begin 0 ? M8 V2 e1 y4 n: B& c! r9 f9 Z
prime:=false;
$ _ c! k+ B e: S0 Tfor i:=1 to l do 6 } ^) s* D N( u
if pr >=x then break - r$ W% s' e+ l8 h1 S& k
else if x mod pr=0 then exit;
. n( |$ z' |2 U1 ~; q# @prime:=true; * d, M2 Y5 \1 @, y4 C' D: H1 j
end;{prime}
4 d0 i5 e5 m' T- {* W& Z* _1 f0 F5 b
2. : G: V) i8 J1 E' z7 y. r, M
- o) m/ ~5 w8 t9 I0 j: D- L3. , _9 S: n& U& {3 ^! _9 L4 `; |
% v8 R# J2 [3 V$ R2 U6 t3 N. g4.求最小生成树 1 V& I- B U- b( L
A.Prim算法:
- r( U; [* h1 C* U; T- K# Dprocedure prim(v0:integer);
% g8 Q# b9 _, Q: l" Rvar
. |7 o8 }4 {4 W8 Llowcost,closest:array[1..maxn] of integer;
( q0 U" \% }; d7 P' }i,j,k,min:integer;
% j. M1 O: E% x! u! z' Ebegin $ b7 f% O1 Q8 S0 o4 j- _
for i:=1 to n do
/ h; F2 X& u2 vbegin 3 K7 I- x# ^% [. o
lowcost:=cost[v0,i];
2 h! {4 [6 G- B2 ^+ t0 \closest:=v0;
& j- {! B/ K$ Y# W3 @% c& ?1 Cend; 9 n/ \( y) Z" U2 o4 c5 j# D
for i:=1 to n-1 do : i! g/ y1 ^: ]- O: [
begin
) X& s5 i% I1 }5 V- O{寻找离生成树最近的未加入顶点k} , B; F8 |0 u2 m* b' u5 W
min:=maxlongint; |* q+ O' H) V# H$ ]
for j:=1 to n do
5 ]% p4 A. _0 e. e9 y7 G' Oif (lowcost[j]< min) and (lowcost[j]< >0) then
8 b/ y; X& N8 q. u& |9 Ebegin
$ K! y. u; A/ p/ R+ }min:=lowcost[j];
# g! R- m$ S, o$ F- h7 @' Yk:=j; 6 `+ T8 d! o" b6 k' Q. S
end; ; v/ b' [( O, u; E+ P
lowcost[k]:=0; {将顶点k加入生成树} 9 ^) U# p0 ]6 V4 H! Z+ C5 C
{生成树中增加一条新的边k到closest[k]}
% H. w6 ?" f2 ?. I{修正各点的lowcost和closest值}
( o9 ^' w" x/ J- O" M5 T* `' s) J# rfor j:=1 to n do * G' y. u+ w) z
if cost[k,j]< lwocost[j] then ' @. r7 D8 U. D3 u9 |
begin 0 C1 U8 o' N2 c6 @: h
lowcost[j]:=cost[k,j]; & T' G8 J9 M' F' ~! {
closest[j]:=k; ; `: O8 |4 K; c2 R4 A
end;
/ X# i! [0 S- N9 Send;
% o, h% A' c" s+ r+ v/ ~end;{prim} $ d* S3 E0 u8 Y, q5 s
B.Kruskal算法:(贪心)
! p1 @. r; e4 H按权值递增顺序删去图中的边,若不形成回路则将此边加入最小生成树。 ' K* w: u! W% B+ r* M
function find(v:integer):integer; {返回顶点v所在的集合} 0 A1 e3 v7 H7 o
var i:integer; 7 n: o( \9 j# B; d$ T
begin ! t" g! \) `5 ~6 ^( {: M
i:=1; 6 ~2 [. t! O" D( S z8 \4 _
while (i< =n) and (not v in vset) do inc(i);
, m! J, P2 o0 qif i< =n then find:=i 9 L% X+ U% K, P& V
else find:=0; + U5 l; _8 j( Y, T
end;
; Q8 Z# K3 B+ F# {7 K# d+ C4 Pprocedure kruskal;
# v2 U6 J1 R$ i& a# Q$ svar # I( o; x8 {$ v2 I, Y# {- C; F8 ^
tot,i,j:integer; 3 G& R& d' ^) [4 }
begin
" [- }2 l3 C' o0 z% |7 h7 g, N% u; Qfor i:=1 to n do vset:=;{初始化定义n个集合,第I个集合包含一个元素I} # j6 y% H, n' ?5 c( B# u
p:=n-1; q:=1; tot:=0; {p为尚待加入的边数,q为边集指针} . q6 \. |5 K: T, N# D7 {
sort; 4 W, O: L7 N ^5 S/ c/ G+ G
{对所有边按权值递增排序,存于e[I]中,e[I].v1与e[I].v2为边I所连接的两个顶点的序号,e[I].len为第I条边的长度}
0 G3 g% B$ T3 M' F& z: ewhile p >0 do
' |$ Y l S- m. F: Z9 i. I+ [, Rbegin
; B! k& D" N# {4 P+ p' Ai:=find(e[q].v1);j:=find(e[q].v2);
' n1 m! F4 T' B5 U$ nif i< >j then
$ o1 T8 ~" P( l- d( P3 Tbegin & R9 ~( k) P0 a/ b& {, K! ?7 N. T; N
inc(tot,e[q].len);
$ q8 F$ U$ S" ~8 f$ z$ k; V( ?: xvset:=vset+vset[j];vset[j]:=[];
; j8 N _5 |) r8 mdec(p);
: ^8 n2 N0 E+ Uend;
( |. U# I. {4 s! G: w! P! }inc(q);
. [- C4 \' W2 o& A! J; e% s4 mend;
2 h: z V) A% v- `- M7 gwriteln(tot); . z8 ^3 o* R u7 g
end;
5 } C3 H7 x+ C v4 p, Y2 ~
" u3 U$ Z8 Z7 w/ x1 P% b: x5 }5.最短路径 {; K( Y% a# a$ b' d! h
A.标号法求解单源点最短路径: & J6 Y2 d0 }7 |
var
; i" F' l' g- n3 R" T6 ta:array[1..maxn,1..maxn] of integer; 5 |" y0 \8 L7 Y7 N Y" ~8 w
b:array[1..maxn] of integer; {b指顶点i到源点的最短路径} 6 n- d3 a- f! q( [% p+ e1 X7 q
mark:array[1..maxn] of boolean; & u8 ~; m w, Y' k1 X3 k
& O' i" `) \/ y! Rprocedure bhf; 0 ]5 ]5 Z' }7 c/ g: ?, |
var 0 z6 ?' w( W3 W- [' Q7 F( B
best,best_j:integer;
' {" E( p. w- N* t4 `1 Zbegin
* x9 I; I$ Q a9 j# ^& Gfillchar(mark,sizeof(mark),false); * [ \" v" b) z4 l6 i6 B
mark[1]:=true; b[1]:=0;{1为源点}
" j" I) V6 k( v1 J/ q/ e6 nrepeat 0 \1 Q% Z7 ]0 J9 S
best:=0; ( s7 N* R% B$ e' X R' C' [! h$ c& }
for i:=1 to n do
7 s/ S: o3 y% U: P1 [- OIf mark then {对每一个已计算出最短路径的点}
' M# J; A! e+ |( b# ]/ lfor j:=1 to n do
- f6 X( J7 F/ k% l+ K4 ] Bif (not mark[j]) and (a[i,j] >0) then
& _5 C: ?- t% F. f1 {2 ]if (best=0) or (b+a[i,j]< best) then & f+ p% B% i$ b' Q6 l
begin
2 R C0 z' d9 p& J; Kbest:=b+a[i,j]; best_j:=j; " O6 y0 S8 K. ]" E
end;
8 A$ t3 B! u2 { Z9 p \& E8 pif best >0 then ( _2 \. k( d( ^$ O4 d/ Z8 N" g. G; |
begin ( N9 c' G" f3 K ?- Q& S1 I
b[best_j]:=best;mark[best_j]:=true;
% P' t% B) [! b0 b5 o6 jend;
$ y$ Y3 J) O3 U/ muntil best=0; 8 r0 i2 k2 R8 ], s$ l( F; b2 h* O6 E
end;{bhf}
$ a- z' K6 r- a2 y
" U/ r$ x& ^! ?, BB.Floyed算法求解所有顶点对之间的最短路径:
6 t' ]) |: J" @* D; U4 qprocedure floyed; # ]- y6 Q( q7 s! m a6 ~" q
begin
6 x; ]. S; W7 ]3 E9 {0 E1 ifor I:=1 to n do , n) u& ?1 A. f* P1 s. j
for j:=1 to n do 3 J# D1 H) m1 E' A, T3 M& X
if a[I,j] >0 then p[I,j]:=I else p[I,j]:=0;
" V7 I. p0 A! o5 Q{p[I,j]表示I到j的最短路径上j的前驱结点} . G( G0 ~8 \: B8 i3 b9 h' q; C
for k:=1 to n do {枚举中间结点}
" x: G" ]/ r7 v& d3 N( q# t8 Xfor i:=1 to n do ' k4 C0 M- [8 ~6 L
for j:=1 to n do " X+ H8 v# J; s- I- H0 D3 q1 ?) c5 E2 p4 D
if a[i,k]+a[j,k]< a[i,j] then 8 ]# W% d7 F6 r# |" r
begin : v1 T! s+ A% ?3 _: `
a[i,j]:=a[i,k]+a[k,j];
+ K# }) n: x$ F P, I% bp[I,j]:=p[k,j];
" `) s* w7 n& m) f) Fend;
( k, D& X7 P/ [5 C' `end;
' R2 t5 \3 \) HC. Dijkstra 算法:
2 B2 x% f+ i5 [0 F& H8 U. y类似标号法,本质为贪心算法。
5 C& |1 H& ~- k% [' bvar
6 `% P$ x, @- Y9 \( a* |, O2 Da:array[1..maxn,1..maxn] of integer;
2 x1 E5 G- f3 x+ N& y/ eb,pre:array[1..maxn] of integer; {pre指最短路径上I的前驱结点} 0 }+ e( G g0 T7 S6 ~6 l
mark:array[1..maxn] of boolean; , Y% g% V6 i" Z) |
procedure dijkstra(v0:integer); . ?5 W- N$ M& `' c( q
begin % M( M6 S. d& |1 }- l8 ^7 V
fillchar(mark,sizeof(mark),false); " e0 M" a7 _( ?$ j) D
for i:=1 to n do
& _( h$ E( P) q( |3 Jbegin
/ g- W" F$ P6 f2 w$ @% gd:=a[v0,i];
5 K2 u8 ~" t/ z) _) L/ @4 vif d< >0 then pre:=v0 else pre:=0;
) ?. Z& b" _6 y& F" h% g( P0 Jend;
, {; ~7 ]! V: _& |$ q$ Lmark[v0]:=true; ( O* _% J! o* k6 h% B/ P' y6 v0 x% Z
repeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数} & E6 Q/ U/ K' O- @0 e a3 E
min:=maxint; u:=0; {u记录离1集合最近的结点}
3 r8 C8 v- [) `% Efor i:=1 to n do
/ i4 |# [1 ~3 d( \/ kif (not mark) and (d< min) then
0 D7 h [2 X. G$ sbegin 9 ^" G. y: K- q
u:=i; min:=d; 5 l6 o4 w3 A. B4 ?' h+ L
end;
; l9 L9 v4 z" m6 @$ s; R+ kif u< >0 then
4 w6 d @1 X% p& k k8 {. I6 k( Sbegin
* y& C8 K7 T6 L. e; }1 ^9 smark:=true;
9 y+ [% k _8 v0 dfor i:=1 to n do
' ]4 }% u% A$ f7 ^) eif (not mark) and (a[u,i]+d< d) then # a& X, @ g5 B" E$ ]2 L$ @1 G
begin
0 V6 ^7 s0 p5 Id:=a[u,i]+d;
! m7 O' G, V' V# ^3 K1 ~* }pre:=u; 7 t2 B! L/ y; H* h- x0 Q* g
end; ! k T5 [5 s0 m% u, [7 ?
end;
; C) u2 Z8 k9 T: e' uuntil u=0; $ }# U9 D7 Q z S3 b
end; 8 O- O( D8 ?( G- c- @: t1 J
D.计算图的传递闭包 9 t" l+ K m, |8 _5 `8 k0 \" s, C
Procedure Longlink; ) ^3 q( b: v0 c" F$ H
Var
- D% L, C" [9 |& l0 h+ WT:array[1..maxn,1..maxn] of boolean; % f% B% _. q* A% Y1 q9 n( L* j% ]
Begin - h# ?1 j( w- Z6 j. e- J
Fillchar(t,sizeof(t),false); 2 {/ c: y$ Q5 U+ j2 E' q/ U8 l
For k:=1 to n do
6 R' C4 L1 |# ^5 U3 iFor I:=1 to n do
1 _) L- ]! S- v) s+ N: ?. T" IFor j:=1 to n do
' V2 F9 y9 S8 b- u- ET[I,j]:=t[I,j] or (t[I,k] and t[k,j]);
2 B/ h% R, H' u) A, D0 G& yEnd;8 B; g$ e: b' c0 c# X' R8 Y2 y
( x/ S: J3 @) Y0 f1 s1 w) Z/ d4 O: g0 V |
zan
|