- 在线时间
- 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.数论算法
0 D+ A/ D6 h& E求两数的最大公约数
7 W6 k" Z" [# o! ^" x0 O4 X1 Ffunction gcd(a,b:integer):integer;
/ }, u2 Y7 O1 x8 Gbegin 8 _; H3 Z8 V0 \8 |1 `0 J! e
if b=0 then gcd:=a 1 j6 h! E- |5 @) w. h) G
else gcd:=gcd (b,a mod b);
. r& x* }/ S2 D& Uend ; / j2 |% I1 r6 J, W
% q9 J9 v" r" b7 \! T求两数的最小公倍数
o5 u& p1 U) ]function lcm(a,b:integer):integer;
a2 V: E. D# K# n N Bbegin
2 f z9 x& P- s, a) t: _: s7 A5 iif a< b then swap(a,b);
5 g1 _+ ~3 S3 f: I+ x- glcm:=a;
0 Y% }: `# n1 e cwhile lcm mod b >0 do inc(lcm,a);
$ A# M& N* B" }1 f7 R7 f* Vend;
& X( e( t- {7 d+ M# V! b, d% v: W( N6 r& x! m
素数的求法 0 ^0 ^- E7 U; j
A.小范围内判断一个数是否为质数: 8 b/ v" P: `0 N7 w8 Q
function prime (n: integer): Boolean; $ k% x7 @3 S2 w- l
var I: integer; . M. z8 y. c* ^# B, r) r7 V- K
begin 6 r) \; `% b- C4 Z$ f4 O% K0 s" G
for I:=2 to trunc(sqrt(n)) do ! A s! @; \. I# H5 G C
if n mod I=0 then " T1 I- c, ?: S$ u9 T2 j
begin . n4 c8 F8 C' d. ?: C }
prime:=false; exit; ! S L4 U. a/ O; S
end; 6 R! ~, E: B6 D# R: ]! q' c4 l
prime:=true; ! E/ L9 |5 w0 }# z/ k! S
end; + A* {9 H A- G
0 f7 R! C1 A! o' k- E) B) E( x! K2 ]B.判断longint范围内的数是否为素数(包含求50000以内的素数表):
) q$ _& _) m. H4 Z5 |+ S% J1 o3 gprocedure getprime;
8 X4 j! O: o- V/ O7 Xvar # W. P% ?. u/ j8 X
i,j:longint; A' a/ b0 n7 d+ W) H
p:array[1..50000] of boolean;
9 j7 h$ F; ]2 ?7 k3 L" q+ Fbegin 3 X$ L. m( x. k8 `
fillchar(p,sizeof(p),true);
6 Z( ?$ _ P6 ^: u0 L7 ^* X& x" fp[1]:=false; " q- h% u5 l! D) G# k' L
i:=2; % W: B% L3 o- s4 Z' O5 K* ?
while i< 50000 do , L* c9 |, R: z
begin 3 F/ N7 Z) E) s6 p
if p then
6 I3 G: L8 U% L3 _) g! b2 }begin
; M9 @ \ i- D2 Y# Z1 Wj:=i*2;
2 k q) ~+ z) [3 J- H% vwhile j< 50000 do
4 L0 N6 q; f% Ibegin
4 L3 g5 M+ I; Np[j]:=false;
( G# j7 U9 q2 V" F( |3 {3 Ginc(j,i);
! a d/ R; D$ {4 _, vend; 0 H- E Y* w' Y2 U
end; . Q# {: e+ }6 j j$ V# a
inc(i);
5 v( |0 h6 r: `end; 2 E. ^! Z7 ^+ g% O: n$ X% U
l:=0; , \# I7 a/ ?2 [+ i4 t
for i:=1 to 50000 do
# p/ h0 o# b& `5 A; l& e7 j! Tif p then
2 j4 |3 \/ h1 W. {4 f4 Fbegin
5 ]$ e9 E3 k; m" Winc(l);
) h! y a' d1 W0 o! T6 {pr[l]:=i; 4 w; f5 w& A# u; _ S
end; $ L7 _; ~4 X1 [+ p! K3 S9 c
end;{getprime}
; {. B) R6 S+ k7 z" s0 O5 pfunction prime(x:longint):integer; ' i. w3 t; O! H" C: i* U
var i:integer; 5 I# k. m# t) t2 Y1 s- b
begin
. ~5 \; m1 x5 B3 r' G; T$ Aprime:=false;
* f- U, _7 X, @ kfor i:=1 to l do - A% x9 F3 p) }6 n) O! ^# [
if pr >=x then break " @' f3 M$ S- _; f
else if x mod pr=0 then exit;
( f7 x# ?' v: yprime:=true;
0 O k! c" J% [$ l6 zend;{prime}
! {8 n. A# D6 M/ ^3 o) s
& w, `$ c3 y, h( j s- |2. ; W" ^# k: ]/ G |
: |) K4 ^, {- P M2 m" y3.
* T6 F( b; g- ]: I8 }
7 P& I6 B Y0 `% H3 _* K4.求最小生成树
# G! G6 K" p0 P/ q( Z5 AA.Prim算法:
( r' }6 g; o- G6 Y4 n! {procedure prim(v0:integer);
& C2 J. E6 @8 f( G% Evar
# w. I, g6 v$ j2 dlowcost,closest:array[1..maxn] of integer;
2 i6 P- O/ h9 Pi,j,k,min:integer; 9 T- w* I% S; J( [1 c! d
begin
" X4 D* I8 s/ j8 r9 N' c; H2 a! @' Yfor i:=1 to n do P# k; Y! ^" c; |
begin % ?9 I# {1 B! L* n4 G
lowcost:=cost[v0,i];
% r8 B4 P0 h8 C* H' B @closest:=v0; 8 l0 f, Y* K) t1 T$ l/ f5 C* [! Y
end;
) l5 Z' x$ Y7 D# t( v+ T5 A' G) efor i:=1 to n-1 do ) [0 g1 ^9 v6 C3 X( b# O3 K8 |/ u0 A
begin
+ v" j) r, T: |. C5 r{寻找离生成树最近的未加入顶点k}
% l# C/ a' O5 q* {' M- u G3 w, fmin:=maxlongint; ) W" P5 @1 t& U$ P0 Q8 ]4 a' @
for j:=1 to n do , s+ u: e) u$ B4 }2 S
if (lowcost[j]< min) and (lowcost[j]< >0) then
' k5 ^8 N9 T1 p( `begin T. z8 x0 U1 i- r. n% ]! _
min:=lowcost[j]; 5 @8 A; N( _7 p+ I
k:=j;
- ^$ @$ K- \8 Y; ~( \) Hend; 7 r' x8 B6 d. w( H
lowcost[k]:=0; {将顶点k加入生成树} : J8 Z- B6 y; _9 |! v" p) ~# z/ y& M
{生成树中增加一条新的边k到closest[k]} 8 G W; n0 q# t
{修正各点的lowcost和closest值}
7 Z& x3 w0 c& q9 ?for j:=1 to n do
1 s& H1 d8 A4 \0 h* J) V) lif cost[k,j]< lwocost[j] then ) d0 M. j+ L7 M! s2 d/ U9 {4 P- N
begin
! {+ A( C& I6 a5 @2 Nlowcost[j]:=cost[k,j]; 4 \7 E; @0 W2 G, Z" j
closest[j]:=k;
, q8 s; V' ]- `end;
6 l- g: p3 ^1 s5 y1 t/ jend;
6 }: ?$ N, m/ H/ K# ^- Yend;{prim}
4 ?/ P0 Q/ g0 G; C. n, `B.Kruskal算法:(贪心)
6 R" H1 v# P) F1 ^% |% ~按权值递增顺序删去图中的边,若不形成回路则将此边加入最小生成树。
3 }. k& Y9 p0 P6 Gfunction find(v:integer):integer; {返回顶点v所在的集合}
% r& \2 a6 G! M& ^2 {/ z D( K' pvar i:integer;
2 \* c- u, K8 s0 F6 mbegin
# Z& W6 [: ^3 k0 i( E: T% bi:=1;
& z1 o9 X# \/ B: R5 D* z) J1 c6 zwhile (i< =n) and (not v in vset) do inc(i); 4 v5 D( [- T8 z
if i< =n then find:=i
# q; K/ Y' T: V, Welse find:=0;
X4 n4 H5 Z$ A% R oend; 6 `$ G; o! M8 {1 b* `/ o
procedure kruskal;
' o4 U- y& R$ ^var " x* J6 R4 y% X% V! p& f4 G
tot,i,j:integer; 5 H- N$ F3 W2 Q+ P& A1 c
begin
+ [& @3 N' E& W) ` s6 D* w+ V/ K8 ~for i:=1 to n do vset:=;{初始化定义n个集合,第I个集合包含一个元素I}
" v! B# ^" ~9 d& x) W* N. u* Dp:=n-1; q:=1; tot:=0; {p为尚待加入的边数,q为边集指针} " G, O* \! T* {" N$ j8 r9 h
sort; # Z- [+ q) k, w; R8 a
{对所有边按权值递增排序,存于e[I]中,e[I].v1与e[I].v2为边I所连接的两个顶点的序号,e[I].len为第I条边的长度}
' D& _! R8 N, q+ [3 X4 r2 t$ x9 B" rwhile p >0 do 7 p- E) A& N" E
begin . @! ~7 O2 o; j: k
i:=find(e[q].v1);j:=find(e[q].v2); 2 } \/ _+ O0 }: ^5 N, T) f% c2 Z
if i< >j then & _0 i. S' a9 p" ?" J" |' A
begin ! ]0 @: O; M2 m
inc(tot,e[q].len); 4 E9 q0 S; ? Y, G- M. ?1 U
vset:=vset+vset[j];vset[j]:=[]; 0 l% X9 @) |- y. V! x
dec(p); 0 w X1 ~/ b( F' O6 z
end;
" V C/ R1 T7 h8 Tinc(q);
3 y: e9 N. G5 z- z7 T! ?end;
5 [' V- M: ^6 |writeln(tot);
% `+ g% G% o7 xend;
8 B' ]0 K! O+ T* p( |3 K- t3 d1 G8 L2 |( ^
5.最短路径
! w8 _6 X3 l8 P' b+ ?% \$ l% q0 SA.标号法求解单源点最短路径: + S4 ?! z: f$ z2 z M' y n/ r
var ; f) h1 g1 F! T4 C% r9 n
a:array[1..maxn,1..maxn] of integer; ' `7 [: n* r" k
b:array[1..maxn] of integer; {b指顶点i到源点的最短路径}
/ h( ?3 X+ [- T5 v {7 a( d& F* _mark:array[1..maxn] of boolean;
, y" v+ U% V9 d' u4 h& O* y& p' D( [8 Z& l, K% l
procedure bhf;
! o6 Z4 h, U7 [$ k- P! _5 ?. ~% l" svar + ?* x' C, K5 A' x ?- u+ v5 o
best,best_j:integer;
; F4 b6 v. D6 J2 D" j5 w; ?2 Hbegin , e4 q. k/ Z9 J$ i; U) `/ v7 e
fillchar(mark,sizeof(mark),false);
' C I' T' r: H8 h3 Kmark[1]:=true; b[1]:=0;{1为源点}
" {' k4 d" N( T7 K' U- j: e7 [repeat ; @; o" ]' f5 O% P6 M( q l( l) {' q
best:=0; 9 c+ d4 i, a! ]' V3 z; T/ m$ [. q' u
for i:=1 to n do . h2 i" g; j; @6 ^- ]2 d
If mark then {对每一个已计算出最短路径的点} ' K$ [1 I; f) I# V7 S6 Z
for j:=1 to n do $ C5 d6 j; u! t# |3 z
if (not mark[j]) and (a[i,j] >0) then
. x* v1 v: a4 ?/ U+ ~if (best=0) or (b+a[i,j]< best) then 5 Y7 C- ~) v$ e0 C( o u& f
begin ( G$ M. F; `' N6 f
best:=b+a[i,j]; best_j:=j; * s0 y. j# w/ \. V
end;
N0 n: u7 e0 e+ [7 j" M" {; dif best >0 then
% V, A; u0 A" k- ~' t0 x8 f8 r6 mbegin ) s/ ]5 c2 H0 ^
b[best_j]:=best;mark[best_j]:=true;
( V& C# i' k% c! S+ u- t1 ^5 lend;
' T$ Z; E0 x; C( ~until best=0;
- r$ O3 I2 c" F+ o+ K3 y9 oend;{bhf} ; a1 M! W/ i5 Q4 n
% X, ^2 O) W3 Y5 R. vB.Floyed算法求解所有顶点对之间的最短路径:
0 n! O- U7 w# A+ v5 u3 ]* A! zprocedure floyed; / n g4 I4 [& x# f2 K ]
begin 1 C1 i7 ~. x& Z! _% g, w
for I:=1 to n do F1 {1 |3 c- o% a# }; A1 u
for j:=1 to n do
) X5 ]* N1 a" ~$ n( Mif a[I,j] >0 then p[I,j]:=I else p[I,j]:=0; 6 z0 }4 B! ^3 |# E
{p[I,j]表示I到j的最短路径上j的前驱结点} " ^2 M6 [$ \2 f. ]9 o6 y) W
for k:=1 to n do {枚举中间结点} " o) }3 y& u N/ f% f
for i:=1 to n do ; v( M- q( r3 K( o) |& I& P
for j:=1 to n do
U% ?/ L+ g' \& l4 mif a[i,k]+a[j,k]< a[i,j] then
- F; L P9 }2 D/ lbegin * L, j% K6 C F# l
a[i,j]:=a[i,k]+a[k,j]; 7 m& j q3 l9 m- y
p[I,j]:=p[k,j];
4 E3 B5 c$ Q) qend; , C! @& q: t' R8 r o. S: y4 j2 Q
end; 7 v6 J1 V- \0 ?1 d1 `' z4 Y: \
C. Dijkstra 算法: 9 s* b1 ?8 N' P3 N, r! ?2 {6 e
类似标号法,本质为贪心算法。 * S/ `( ~ e; u9 v4 R" B4 v- a
var
: k; ]4 {7 u0 @" |& ?- N1 da:array[1..maxn,1..maxn] of integer;
8 E- ?+ N$ c- e2 c9 ob,pre:array[1..maxn] of integer; {pre指最短路径上I的前驱结点}
9 A3 f) Q+ Y; ymark:array[1..maxn] of boolean;
@7 }- ], P J; C s H4 c/ F/ Bprocedure dijkstra(v0:integer);
/ ]( S4 B+ H4 @: Gbegin
) j, X2 p, @4 h; rfillchar(mark,sizeof(mark),false); 8 z2 G7 `7 A, _6 K
for i:=1 to n do ( ]+ j" ?) u8 q8 t
begin
, W- l% U" q3 Fd:=a[v0,i];
( s$ K0 J3 A$ j) J8 S( ]if d< >0 then pre:=v0 else pre:=0;
- r6 \: X) l$ F; D# Y( bend; 4 s! a" C' X' r/ \( y
mark[v0]:=true; / M- w+ s, h$ N
repeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数} - p7 [, s8 n4 @7 m# |; b9 B
min:=maxint; u:=0; {u记录离1集合最近的结点}
" @$ T! d7 Y. e( \0 Afor i:=1 to n do # R% x- G$ u: p
if (not mark) and (d< min) then 0 z) Z& r' @5 J: X. Z8 T# [0 L
begin
9 H9 m1 o6 A2 o, c0 eu:=i; min:=d; + E3 K8 x9 ~* G7 K% B; L2 j
end; " S+ e. u7 s) j" C: a7 |3 x
if u< >0 then 2 |4 z2 d$ v* q- I; `) Y/ v
begin ; }$ x% b5 V. c7 {
mark:=true;
" v# E9 I- d1 U/ F( Kfor i:=1 to n do
8 g. q+ ]- L: e7 x4 Fif (not mark) and (a[u,i]+d< d) then
8 V+ d* ]" g7 f/ _1 G% ~begin
- F$ O& t! C2 B8 v/ ?9 W, L4 ]6 G) sd:=a[u,i]+d; & a! d2 M! |* Z" W& M
pre:=u;
2 D1 X' s2 A) m8 Cend;
& y5 d% X3 j8 W; T# V' Qend; " h9 Z; z; T+ `% t2 p1 f+ ? ?% T! Y
until u=0; / E0 e: [3 P( A3 ?0 t$ |
end;
; x2 a( R3 G0 uD.计算图的传递闭包 " i- c/ ]2 O. t8 B# Z
Procedure Longlink; * n1 l7 N( \( J, t% A1 `
Var
' e: ?# \8 {4 k# [T:array[1..maxn,1..maxn] of boolean;
2 U( p; o% k/ J. {: H- J/ mBegin
, a2 {* y$ [* M! U& p& NFillchar(t,sizeof(t),false);
2 h" O4 v4 R6 ?' ?' c6 ~6 dFor k:=1 to n do 6 ~; @* T( e3 Z& O1 c0 i
For I:=1 to n do
8 x- C' M; c/ ]( w3 nFor j:=1 to n do
' t: I0 b0 e" Z' I @T[I,j]:=t[I,j] or (t[I,k] and t[k,j]);
* s W X! i; Y1 r/ c% I& rEnd;
! {2 W6 x+ U7 A! \. o
& z' X, u" C( _. \ |
zan
|