- 在线时间
- 1029 小时
- 最后登录
- 2017-4-30
- 注册时间
- 2014-1-21
- 听众数
- 213
- 收听数
- 2
- 能力
- 100 分
- 体力
- 15813 点
- 威望
- 98 点
- 阅读权限
- 150
- 积分
- 8573
- 相册
- 0
- 日志
- 0
- 记录
- 3
- 帖子
- 1549
- 主题
- 715
- 精华
- 2
- 分享
- 0
- 好友
- 542
TA的每日心情 | 开心 2017-4-28 17:18 |
|---|
签到天数: 415 天 [LV.9]以坛为家II
 群组: 乐考无忧考研公益讲座 群组: 2017美赛两天强训 群组: 模友会交流视频 群组: 群组: 国赛讨论 |
1.数论算法 9 k Z1 g) y# Y
求两数的最大公约数
/ {* i9 }8 x. i, S& X5 v' u" L: [function gcd(a,b:integer):integer;
3 P0 e. ~" `: @ ~1 u: X# C8 F5 h0 cbegin ~) k1 y6 o5 e" l
if b=0 then gcd:=a
4 G3 R: l- T& {+ Y6 U- o4 felse gcd:=gcd (b,a mod b);
* @# Q X4 a, k. Q/ t7 Fend ;
& J: E% {8 r/ ~7 t5 V4 e# v8 T0 B
8 A; k% u& z* }* ^4 v求两数的最小公倍数
, W2 m; E8 J6 f+ I( G7 m8 Q$ Jfunction lcm(a,b:integer):integer; * G; {! i+ Y' x9 t
begin
8 q! W$ H5 I6 a7 I4 J9 C0 c9 F) \6 `5 kif a< b then swap(a,b); n' |4 u& M# w/ w: r
lcm:=a;
- I. Y4 t* b2 j J' O9 E Uwhile lcm mod b >0 do inc(lcm,a);
9 T7 M. _* B/ V" e8 ]end; 6 z9 Y ~! Z" U* j" X
" V; A9 P2 [# f( `: e, h3 H( t素数的求法 O( a4 J3 R4 |* Q
A.小范围内判断一个数是否为质数: 2 l0 A4 {. j( |8 b9 {3 @; H! n; i
function prime (n: integer): Boolean; 5 Q8 e H4 e) _4 s- E
var I: integer;
+ ?) t5 v" p1 g. qbegin " C1 N- f- H9 p! u) @% [
for I:=2 to trunc(sqrt(n)) do
6 }+ g! x2 l$ y2 p6 w/ O% hif n mod I=0 then / g* \5 C8 s5 e0 a" ~2 g0 C
begin
. Y G1 t3 _- r# Pprime:=false; exit;
6 v, \& z3 C9 K9 O2 Lend;
& @2 w+ P, a9 n0 {% V2 j1 Sprime:=true;
. Q# g, c: Y2 M% M$ ~end;
( [ P0 a- U2 B ?8 {( ?% c' h1 s9 @- H# I8 B2 U! p) m) g
B.判断longint范围内的数是否为素数(包含求50000以内的素数表): ' r+ F. x9 v: l& E; {
procedure getprime;
) q; H: y2 X$ z6 w) R9 R! v& fvar
& M5 i* k$ ?! D$ J% a$ I6 Di,j:longint;
" J( |- j1 |# ]- n. o$ }& I, ]p:array[1..50000] of boolean;
- H7 G0 g) l$ E5 C" M7 fbegin
3 c5 \7 X4 x$ f6 Q8 ]1 Kfillchar(p,sizeof(p),true);
i, P" V: u; L7 a# ]p[1]:=false; ) Q+ \: L9 b6 o% Z. t" Y$ m' j
i:=2; 8 D: a0 E( w9 o! X L1 I2 O
while i< 50000 do
3 g* z/ I- Q8 a% F5 tbegin , ~5 k, O( x" E" x0 F% z
if p then
8 Q* R8 g8 |2 m, hbegin 1 Q! R" w) K7 m6 ~
j:=i*2; ( M; r( O$ t8 e8 e& X/ n' u9 U
while j< 50000 do
% C2 }4 p& M* P# w. v$ Q6 c+ pbegin
2 C5 d* _* V7 q& A% Mp[j]:=false; ' i) a& @1 L+ I5 H! Z- ?
inc(j,i);
8 E/ \8 {! z, f, b$ E4 u: i: cend;
# X* k3 o) a% W5 ~" zend;
6 G) p5 G5 T3 q% U+ Y% F( ?; Winc(i); 6 z1 c+ `4 Z; Y" ?2 k8 `) q
end; . h6 ^0 ~/ d# B7 a
l:=0;
! h0 G# z; l' b1 x9 bfor i:=1 to 50000 do
# [) p7 l7 w5 m$ Z* Yif p then * @9 g3 P3 G+ j, C/ D- _% A2 A
begin
P% n' |! ]" {, D8 A5 p2 ainc(l);
6 ~% s9 a6 p" C2 i! R/ `8 f1 ~! jpr[l]:=i; ) e! z7 z9 e: e7 T; {$ |! ^! [) K
end; 1 A, i) Q. w" V% X$ A' Z k
end;{getprime}
( Z/ G5 h( n7 j2 q2 p* @( lfunction prime(x:longint):integer; . J' ?8 P! l5 m" L, p" T, ]
var i:integer; * G$ t0 \- s% R' D' N7 b9 p3 E
begin
: P3 X! _/ C# xprime:=false;
( k! ~% z( O+ i6 l& yfor i:=1 to l do
0 d) O+ c) P1 Q* V4 aif pr >=x then break ! [0 r" K0 K2 |3 ]. @& V& }1 w" {
else if x mod pr=0 then exit; & l! s6 J9 x3 \
prime:=true;
, s n* T6 b1 y$ Z5 L" G( {6 t! oend;{prime} ( s# a. k/ z2 q& Y
6 k) x) ~/ R+ j6 m$ Q, F2. 4 V3 X, F; V- c/ ?5 n
1 A: P% c; W. E6 C c, s! Y
3. 5 W2 H6 t$ ]! B
. Z8 i1 m0 o8 x
4.求最小生成树
% K* u& T( D8 ]% m+ MA.Prim算法: 2 ?! l/ {! T$ k$ M/ }' v7 Z
procedure prim(v0:integer);
0 [( F# x! r2 |1 ~* v. w$ xvar ) g0 d5 u9 R9 ]( m) e
lowcost,closest:array[1..maxn] of integer; ) G0 G- J0 C- X2 m- C! X5 H; K
i,j,k,min:integer; 6 k6 _$ e* U' j2 P' _! e9 J0 l" H
begin
1 [' B4 f6 e5 q0 w% G- M2 [( Y) zfor i:=1 to n do + d8 e* i- | |8 Z5 e: |6 c6 ^
begin ' L" p4 x6 O1 Z
lowcost:=cost[v0,i]; / P$ X9 p/ B, G2 {. ~- T0 V, E: t
closest:=v0; * A. c" e ^! ^+ j. v
end;
7 a0 l7 z p/ E D$ efor i:=1 to n-1 do
3 c) x F1 `9 j2 Q+ t9 l+ z7 Wbegin / O4 ^! y% p- f% m
{寻找离生成树最近的未加入顶点k}
. r5 x9 B/ q+ `8 @9 o4 a, amin:=maxlongint;
- f5 m, \$ m5 S/ P( Yfor j:=1 to n do . |4 q; t, {; O3 F3 o
if (lowcost[j]< min) and (lowcost[j]< >0) then
6 P( Q( _# [1 W2 P9 Z0 Ybegin 8 ? A z1 A* h1 I8 u
min:=lowcost[j];
% j) o! f) w2 t* a6 fk:=j; $ \$ c, X$ }6 y. h- U- q: n
end;
1 A! F; X- M; w" Z8 j9 Clowcost[k]:=0; {将顶点k加入生成树} $ a( h4 O' y0 v/ m4 L
{生成树中增加一条新的边k到closest[k]} d7 S* W% D( B1 x
{修正各点的lowcost和closest值} ' g# ^6 H6 z: w- t( K! U
for j:=1 to n do : X3 @+ b( Z1 f$ d, z7 P
if cost[k,j]< lwocost[j] then
9 s1 V" z! R. V$ R* s# ~begin % ^, T9 \' w$ W
lowcost[j]:=cost[k,j];
( M, D2 t6 v4 O! r6 cclosest[j]:=k;
6 x6 E- L; `, }9 o o2 Uend;
[9 n) P4 ?+ bend;
$ O. w# b) M. K; ]2 s$ jend;{prim}
* Q- o3 R* m7 f5 ~3 hB.Kruskal算法:(贪心) " d a% f) W4 I; L1 l9 [0 {
按权值递增顺序删去图中的边,若不形成回路则将此边加入最小生成树。
* L( E9 W3 m3 T7 L6 X6 l- ], @function find(v:integer):integer; {返回顶点v所在的集合}
/ r2 @6 J0 J3 D5 h; }; D6 zvar i:integer; , C( D( W. h) r- K- z
begin $ b3 D; `$ Z1 ~# | X% a
i:=1;
3 \2 b0 `1 h+ J9 w/ P. t' H Vwhile (i< =n) and (not v in vset) do inc(i); 5 e" |9 y# i4 c0 c1 E
if i< =n then find:=i 9 m6 I" b4 I# r2 e6 f
else find:=0;
, y2 @3 d- I: s9 A' [4 }end;
% h5 Y7 c0 v- [2 m7 ^procedure kruskal; . O& I/ Y+ I, O5 a. O L4 n
var
% f+ O* X4 q! wtot,i,j:integer; - Y1 u4 Q; ^2 j1 v/ {
begin
8 o& n6 g0 b! {; w" o5 ~for i:=1 to n do vset:=;{初始化定义n个集合,第I个集合包含一个元素I} 7 N6 t7 m4 A% K& D6 L
p:=n-1; q:=1; tot:=0; {p为尚待加入的边数,q为边集指针} 9 [; A7 u& b) j! W4 T
sort;
0 F( D6 ^8 z0 Z/ J{对所有边按权值递增排序,存于e[I]中,e[I].v1与e[I].v2为边I所连接的两个顶点的序号,e[I].len为第I条边的长度}
1 q2 O1 t) Q }1 V& cwhile p >0 do
8 a" [6 L4 b) q1 z0 g$ i8 Vbegin
7 g3 |/ z+ g b& s' W- ri:=find(e[q].v1);j:=find(e[q].v2); A* ~- v. l8 X8 T
if i< >j then ( x( r! z# o- Y- \6 {" m, @, J
begin ; E% G$ ]; Y6 `; r2 f0 r
inc(tot,e[q].len); ' H4 \* \) L6 q; Q2 e8 A
vset:=vset+vset[j];vset[j]:=[]; ' h8 f8 |% h+ A r3 m% Z
dec(p);
+ w/ L, R' |0 s* t, f" s- bend; 6 Q/ _* c y+ g% h1 ~/ z1 i/ I. x) h
inc(q);
7 _7 @0 ]4 s$ nend;
. s/ E; V4 C: A. }! ~: t; Cwriteln(tot); ( b: K- Z% D$ {9 c. ?9 y1 R
end; $ n1 W1 j9 \: S+ ?! x
& J4 Y" I/ R& n& G
5.最短路径
6 C( o; Z4 A E4 XA.标号法求解单源点最短路径: # f2 U/ {( }! x
var
" n2 b5 m' ~: u9 }7 }a:array[1..maxn,1..maxn] of integer; 7 m2 g0 i& [% a% Y( t
b:array[1..maxn] of integer; {b指顶点i到源点的最短路径} + Z" K7 b$ a& c5 t8 u. I
mark:array[1..maxn] of boolean;
$ V: y% a- G% z8 D/ p1 P9 [! X2 h+ @$ Y. C
procedure bhf; 2 h, O/ ]1 Q W6 e) x
var
3 U1 g' y. W& k! K- g Ebest,best_j:integer;
" o, v7 {- S6 i) P% j, h, Jbegin $ L8 P' o1 F1 Y6 u
fillchar(mark,sizeof(mark),false);
" m1 @9 ~0 V5 C1 {mark[1]:=true; b[1]:=0;{1为源点}
. w4 r7 {) R8 Q" N4 I8 z7 ]repeat
?9 X. T9 F- L- j- Ubest:=0;
* M' n3 q; A0 l6 ]8 U/ }0 t. z+ A$ Jfor i:=1 to n do
, T% S4 M/ W" Y' mIf mark then {对每一个已计算出最短路径的点} ; G4 f4 K! e! o% u
for j:=1 to n do
! k C0 j& ?/ i+ S8 Jif (not mark[j]) and (a[i,j] >0) then 1 A+ v4 Q* e9 ~! e# S" t0 ^2 `6 _5 m
if (best=0) or (b+a[i,j]< best) then ! ~! U6 S8 F3 R# d: i
begin
- J7 R% ?7 z, F _$ m& wbest:=b+a[i,j]; best_j:=j;
4 t8 T* k0 ^; G# @" gend; $ h: J/ j2 \1 V# N4 K8 u# _
if best >0 then # D- T9 @9 c# U0 W7 _
begin
9 |" s, ^" R+ ?b[best_j]:=best;mark[best_j]:=true; . n8 ]9 |. D( J8 H$ p8 r: \
end;
% S/ c9 l. r+ p" M$ ?until best=0;
5 @* w* Q; |& ~end;{bhf}
/ }! | R& A$ d" L6 K: o3 t0 w/ {8 J1 C3 g& l
B.Floyed算法求解所有顶点对之间的最短路径: 2 \ a& e# x; N8 Y
procedure floyed;
# T: h( H4 j' s P1 P. }5 pbegin % a. R4 Y; s" }5 B# O( I* L5 _
for I:=1 to n do
. L2 S; r. p' sfor j:=1 to n do
# b e3 W3 a; w8 Eif a[I,j] >0 then p[I,j]:=I else p[I,j]:=0;
0 \& H3 p* I( E3 o% j- P# j{p[I,j]表示I到j的最短路径上j的前驱结点}
1 ?4 L a: E+ \; Q% Ofor k:=1 to n do {枚举中间结点}
* h8 t b) w0 {: `3 jfor i:=1 to n do % o( o N( P u" Y, U+ |! I. X
for j:=1 to n do 7 Y0 }! K- B' ?* I2 V
if a[i,k]+a[j,k]< a[i,j] then M K% ]( d3 V+ e
begin 2 z( g0 `. D) t, L& E/ P' G% y+ J& z
a[i,j]:=a[i,k]+a[k,j]; ; ^9 Q9 s K/ _8 |6 f$ u- G# c
p[I,j]:=p[k,j];
$ i4 G0 H, P8 Y& \- n& ]9 _end;
o1 w3 W* N4 ^0 K0 ^0 }0 wend; 7 d6 ?2 o; Z! F* |' u% a5 V
C. Dijkstra 算法: 0 Z& Q6 g5 [6 @5 p+ B
类似标号法,本质为贪心算法。 ) L% ]9 W0 @4 ~1 @
var 7 o5 M6 y% b# r1 W
a:array[1..maxn,1..maxn] of integer;
+ p7 b/ ^; ~2 q' I3 H6 R: Zb,pre:array[1..maxn] of integer; {pre指最短路径上I的前驱结点}
- A$ G5 n; Q, I8 R+ S# v# rmark:array[1..maxn] of boolean;
& Z* g0 N& q& G' Eprocedure dijkstra(v0:integer); / ]8 U3 y- |, T+ y/ t& p$ K. F
begin
1 n9 g1 F( B8 c8 v) ?3 A# u1 ufillchar(mark,sizeof(mark),false); 7 P* |1 B& d; Y2 z6 T3 P/ v
for i:=1 to n do
/ p3 r k D: i2 W' [begin + f2 p" g# C$ P; V
d:=a[v0,i];
5 D- s& W4 ~# j, eif d< >0 then pre:=v0 else pre:=0;
7 t$ i1 q! K% |1 n3 K- iend;
0 K+ R+ _# [0 r6 F6 D+ smark[v0]:=true; 4 ~/ g! [ Y) x
repeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数}
, e8 C- C' |) @$ N' _min:=maxint; u:=0; {u记录离1集合最近的结点} 4 ^4 u$ k" } [9 |" `( ?
for i:=1 to n do # \9 G; Q0 _. G% Y- u# C
if (not mark) and (d< min) then % |8 R8 \' u8 K, i) C/ t0 n* L
begin . N/ F6 V. Q0 L; S0 _% @! I
u:=i; min:=d;
& F8 a" j' M/ _- y0 I9 S1 g, _end;
" J C- E2 m. f3 n, ?) U, Pif u< >0 then 1 K6 a" j; ^$ j! c* O# \
begin
J+ u t: D( [+ h' omark:=true;
; Z5 a" Q1 H$ M+ S5 n4 Bfor i:=1 to n do
7 U4 T4 I/ ] q# T& P3 D1 L2 |if (not mark) and (a[u,i]+d< d) then
4 o/ W z* ^) gbegin , f/ M+ K+ w% Q% s: F5 u
d:=a[u,i]+d;
! R6 m. S4 l. O* ?pre:=u; % J9 O! X9 s$ k8 B+ s
end;
2 H: @8 B1 u; ^! p3 K; Oend;
) Z6 |% V# ]! W" b9 w3 \until u=0; 0 K8 X) ]/ }8 e5 s
end; / Q" C% b+ x. O
D.计算图的传递闭包
" F' n" e) {, t4 ~" J/ x0 I0 ^Procedure Longlink;
1 M g: Z" L1 o+ d6 oVar # F7 f; \7 P! v8 k- l) V
T:array[1..maxn,1..maxn] of boolean;
6 ] ]' u6 G, z# qBegin g' }5 ~3 g' H6 @* e: B
Fillchar(t,sizeof(t),false); ; l( Q* ~5 s# E/ k& s( K& i
For k:=1 to n do
1 \* n$ x O& ^5 GFor I:=1 to n do / F/ T0 ]5 |! k5 `: s& b
For j:=1 to n do ; p! F/ r6 K1 c6 Z
T[I,j]:=t[I,j] or (t[I,k] and t[k,j]); 0 D) c) E* H) J7 `4 ^! Y
End;4 Z- o7 [! H0 \9 b
1 g/ X: i i2 N/ U6 J4 U |
zan
|