添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

可惜不能参加今年的省队选拔了,退役了。。。
NOIP 2006获得一等奖名单

姓名

学校

年级

分数

李宇骞*

杭二中

高三

400

胡方炜

杭十四中

高二

380

唐铕泽

杭州学军中学

高三

370

张斌狄

镇海中学

高二

360

俞毓锋

绍兴县鲁迅中学

高三

330

裘川

杭州萧山中学

高二

320

方戈*

杭州学军中学

高二

320

陈章义

温州中学

高二

310

黄文昊*

杭十四中

高三

310

刘飞

绍兴县柯桥中学

高二

300

章一超

绍兴一中

高二

300

赵杨

绍兴县柯桥中学

高二

290

刘雨辰*

杭二中

高三

290

徐丹枫*

绍兴一中

高二

280

俞华程*

杭二中

高二

270

詹杨

温州中学

高二

270

裘东盈

杭二中

高二

260

许怿文*

绍兴一中

高二

250

陈思思

温州中学

高三

230

盛哲

杭二中

高二

220

孙楠

温州中学

高二

210

董华星

绍兴一中

高一

210

娄坚

绍兴一中

高二

210

傅一波

绍兴县柯桥中学

高一

210

谢陈宁

温州中学

高二

210

马程杰

绍兴县柯桥中学

高二

200

龚逸伦*

杭二中

高三

200

向阳*

杭州学军中学

高二

200

陈思渝*

绍兴一中

高三

190

朱锋

绍兴一中

高三

190

宋?

绍兴一中

高三

190

张弘毅*

杭州学军中学

高二

190

葛云云

绍兴县柯桥中学

高三

190

陈耀宗

温州中学

高二

190

夏威

杭州学军中学

高二

190

竺旭东

奉化中学

高二

180

陈天南

绍兴一中

高二

180

戴鑫通*

温州中学

高三

180

马超奇

绍兴县柯桥中学

高一

180

张丹枫*

余姚中学

高二

180

陈 晨

绍兴县柯桥中学

高一

180

周子傑

江山中学

高二

170

徐斌

湖州中学

高三

170

周正

杭二中

高一

170

傅晓巍

绍兴一中

高二

160

程何

湖州中学

高二

160

程通

杭州外国语学校

高一

160

王建淼

绍兴县鲁迅中学

高一

160

方宇剑

杭二中

高二

160

张俊

温州中学

高三

150

蒋勇

台州路桥中学

高三

150

赵扬

绍兴县柯桥中学

高二

150

张文霞

绍兴县鲁迅中学

高一

150

闵哲辰

杭二中

高三

150

李颖洲

温州中学

高二

140

王仲禹

杭州学军中学

高一

140

俞红玉

绍兴一中

高三

140

舒昱扬

绍兴一中

高二

140

潘晔

杭十四中

高二

140

张潇

绍兴一中

高一

140

沈怡涛

绍兴一中

高三

140

丁梦龙

绍兴一中

高三

140

陈卓兴

绍兴一中

高三

140

楼欣宇

宁波效实中学

高二

140

周超

绍兴县鲁迅中学

高二

140

朱桢

杭州萧山中学

高三

140

韩佳

绍兴一中

高三

140

NOIP 2005获得一等奖名单(浙江)

NOIP 2005获得一等奖名单
浙江 获奖人数:54

姓名

编号

学校

分数

唐文斌*

I050802

绍兴一中

380

俞华程*

I050803

杭州二中

270

戴鑫通

I050804

温州中学

250

谢文磊*

I050805

宁波效实中学

240

刘雨辰*

I050806

杭州二中

230

黄劲松*

I050807

绍兴县柯桥中学

220

魏越闽*

I050808

杭州学军中学

210

吴越

I050809

衢州二中

210

王远轩*

I050810

余姚中学

200

许怿文

I050811

绍兴一中

200

应圣钢*

I050812

杭州二中

190

朱晟

I050813

桐乡高级中学

180

周金龙*

I050814

温州中学

170

陈天奇

I050815

松阳二中

170

陈思渝

I050816

绍兴一中

150

张路

I050817

余姚中学

150

谢天

I050818

宁波镇海中学

150

徐丹枫

I050819

绍兴一中

140

刘盛琪

I050820

江山中学

140

张金利

I050821

衢州二中

140

俞晨光

I050822

宁波镇海中学

140

张宇

I050823

绍兴一中

140

赖陆航

I050824

杭州建兰中学

140

方戈

I050825

杭州学军中学

140

李锡峰

I050826

绍兴一中

140

胡关亮

I050827

绍兴县柯桥中学

140

任政

I050828

绍兴一中

140

盛达敏

I050829

金华一中

140

胡建丰

I050830

杭州外国语学校

140

孟俊毅*

I050831

绍兴一中

140

唐科尔

I050832

绍兴一中

140

龚逸伦

I050833

杭州二中

140

王旻*

I050834

绍兴县柯桥中学

140

李涛

I050835

绍兴一中

140

谢峰*

I050836

宁波效实中学

140

傅锴铭

I050837

绍兴一中

140

徐源

I050838

杭州学军中学

140

张弘毅

I050839

杭州学军中学

140

谢玮峰*

I050840

绍兴县柯桥中学

140(80.5)

郑海斌*

I050841

绍兴一中

130(75.5)

祝利聪

I050842

江山中学

130(75)

林俊琦

I050843

宁波鄞州中学

130(74.5)

沈方伟

I050844

绍兴一中

130(72.5)

丁海淼

I050845

绍兴县柯桥中学

130(71.5)

郑君涵

I050846

衢州二中

130(71.5)

李青杉

I050847

衢州二中

130(71)

胡立峰

I050848

绍兴一中

130(70.50)

吴仲亮

I050849

杭州学军中学

130(70)

向阳

I050850

杭州学军中学

130(70)

杨洋

I050851

绍兴一中

130(69.5)

姚元超

I050852

杭州外国语学校

130(68.5)

张丹枫

I050853

余姚中学

130(68.5)

盛斌*

I050854

绍兴一中

130(67.5)

国家品

I050855

湖州中学

130(66.5)

第十一届全国青少年信息学奥林匹克联赛通知及复赛名单(浙江赛区)

Fillchar过程全解

Fillchar是Turbo/Borland Pascal的System单元的一个标准过程,它的使用格式是:FillChar(var X; Count: Word; Value),它的功能是,把指定变量X在内存段中所占的低Count个字节赋为相同的值Value, 其中Value是填充的值,只能是Byte、Char或Boolean等单字节类型的值。在Free Pascal中稍加扩展为FillChar(var X; Count: Longint; Value), 功能没变。

[例1]: Fillchar通常用来给数据赋初值。

var a:array [1..10] of arrtype;
fillchar(a,sizeof(a),0);


当arrtype为

  1. real(其他实数类型差不多)
  2. integer(byte,word,longint,shortint都相同)
  3. boolean
  4. char
  • 使得a中的元素全部成为0.0
  • 全部为0
  • 全部为false
  • 全部为#0

这里使用了函数sizeof(a),其功能是返回变量a所占的总字节数,如上例返回:

当arrtype为

  • real sizeof(a)的值为60(每个元素占6个字节,10个元素共占60个字节)
  • single sizeof(a)的值为40(每个元素占4个字节,10个元素共占40个字节)
  • double sizeof(a)的值为80(每个元素占8个字节,10个元素共占80个字节)
  • extended sizeof(a)的值为100(每个元素占10个字节,10个元素共占100个字节)
  • comp sizeof(a)的值为80(每个元素占8个字节,10个元素共占80个字节)
  • integer(word) sizeof(a)的值为20 (每个元素占2个字节,10个元素共占20个字节)
  • byte (shortint) sizeof(a)的值为10 (每个元素占1个字节,10个元素共占10个字节)
  • longint sizeof(a)的值为40 (每个元素占4个字节,10个元素共占40个字节)
  • boolean sizeof(a)的值为10(每个元素占1个字节,10个元素共占10个字节)
  • char sizeof(a)的值为10 (每个元素占1个字节,10个元素共占10个字节)

所以例1的结果就是将数组a的所有元素(全部字节)用0来填充,要注意对不同类型的数据而言,对“0”的“解释”是截然不同的!对整型或实型量来讲,所有字节均为0,则该量也为0;对boolean型量(一个字节)来讲,0表示false(非0数表示true),则该量为false;对char型量(一个字节)来讲,0表示ASCII码值为0的字符,则该量为#0。
Read More...

[例2]:将上例中的fillchar(a,sizeof(a),0)改为 fillchar(a,sizeof(a),1),结果如何呢?

fillchar(a,size(a),1);

当arrtype为

  • boolean 全部为true(1是非0值,表示true)
  • char 全部为#1
  • byte,shortint 每个元素是1字节量,全部为1
  • integer,word 每个元素是2字节量,全部为(257)10。这是因为在一个integer或word 型变量中,它的高、低两个字节均用1来填充(将10进制数1转化为二进制数00000001),结果为:

高字节

低字节

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

0

0

0

0

0

0

0

1

0

0

0

0

0

0

0

1

如果,执行的是fillchar(a,size(a),171),结果又是怎样的?

因为(171)10=(10101011)2,所以,填充后为:

高字节

低字节

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

1

0

1

0

1

0

1

1

1

0

1

0

1

0

1

1


对于integer类型的量,其值为(-21589)10,这是因为integer类型的数据是用补码表示的有符号数,最高位是符号位,0表示正,1表示负,由于本数是负数,补码为1010101110101011,则反码为1010101110101010,原码为1101010001010101,其值为

-(214+212+210+26+24+22+1)10 = -(21589)10

对于word类型的量,其值为(43947)10,这是因为word类型的数据是用原码表示的无符号数(非负数),原码为1010101110101011,其值为

(215+213+211+29+28+27+25+23+21+1)10 = (43947)10

5.longint 每个元素是4字节量,执行fillchar(a,size(a),1)后,全部为(16843009)10。这是因为,对于每个元素来讲,用1填充后变为:

高字节

低字节

31

30

29

28

27

26

25

24

23

22

21

20

19

18

17

16

0

0

0

0

0

0

0

1

0

0

0

0

0

0

0

1

高字节

低字节

15

14

13

12

11

10

9

8

7

6

5

4

3

2

1

0

0

0

0

0

0

0

0

1

0

0

0

0

0

0

0

1


longint类型的数据是用补码表示的有符号数,最高位是符号位,0表示正,1表示负,由于本数是正数,故补码、反码及原码均为00000001000000010000000100000001,其值为

(224+216+28+1)10 = (16843009)10

如果,执行的是fillchar(a,size(a),255),结果又是怎样的?

由于(255)10=(11111111)2,故填充后,补码为11111111111111111111111111111111,它是负数,则其反码为11111111111111111111111111111110,原码为10000000000000000000000000000001,其值为-1

6.single 每个元素是4字节量,全部为2.36942782761724E-0038,这是因为,对于每个元素来讲,用1填充后的结果与longint类型的二进制码完全相同,但是, single类型对此数据的“解释”却完全不同:

  1. 最高位(第31位)是整个数的符号位,0为正, 1为负;
  2. 接着的8位(第30位至第23位)是用移码表示的阶码;
  3. 后面的23位(第22至第0位)表示尾数;

单精度量的值为:±2 实际指数 *实际尾数

①、若阶码=00000000,则实际指数=-126,实际尾数=(0.???????????????????????)2,其中的?代表相应位置上的二进制码(0或1);显然,在?全为0时, 这个单精度量的值为0;

②、若阶码大于00000000且小于11111111,则实际指数=阶码-(127)10=阶码-01111111,实际尾数=(1.???????????????????????)2

③、INF(无穷大)若阶码=11111111,尾数全0,则已达上界,被作为无穷大

④、浮点运算错误:若阶码=11111111,尾数在(00000000000000000000000, 10000000000000000000000)之间。

⑤、NAN(非数:Not A Number)若阶码=11111111,尾数在[10000000000000000000000, 11111111111111111111111]之间

下面,我们来分析二进制码为00000001000000010000000100000001的单精度数(single类型)的值是多少

Posted on Categories Olympics in Informatics Leave a comment on Fillchar过程全解

一、数论算法

1.求两数的最大公约数

function gcd(a,b:integer):integer;
begin
  if b=0 then gcd:=a
  else gcd:=gcd (b,a mod b);

2.求两数的最小公倍数

function lcm(a,b:integer):integer;
  var t:integer;
  begin
    if a<b then begin
      t:=a;a:=b;b:=t;
    lcm:=a;
    while lcm mod b>0 do inc(lcm,a);

3.素数的求法
A.小范围内判断一个数是否为质数:

function prime (n: integer): Boolean;
  var I: integer;
  begin
    for I:=2 to trunc(sqrt(n)) do
    if n mod I=0 then begin
      prime:=false; exit;
    prime:=true;

B.判断longint范围内的数是否为素数(包含求50000以内的素数表):

procedure getprime;
    i,j:longint;
    p:array[1..50000] of boolean;
  begin
    fillchar(p,sizeof(p),true);
    p[1]:=false;
    i:=2;
    while i=x then break
      else if x mod pr[i]=0 then exit;
    prime:=true;
  end;{prime}
Read More...

二、图论算法

1.最小生成树
A.Prim算法:

procedure prim(v0:integer);
    lowcost,closest:array[1..maxn] of integer;
    i,j,k,min:integer;
  begin
    for i:=1 to n do begin
      lowcost[i]:=cost[v0,i];
      closest[i]:=v0;
    for i:=1 to n-1 do begin
      {寻找离生成树最近的未加入顶点k}
      min:=maxlongint;
      for j:=1 to n do
      if (lowcost[j]0) then begin
        min:=lowcost[j];
        k:=j;
      lowcost[k]:=0; {将顶点k加入生成树}
      {生成树中增加一条新的边k到closest[k]}
      {修正各点的lowcost和closest值}
      for j:=1 to n do
        if cost[k,j]

B.Kruskal算法:(贪心)
按权值递增顺序删去图中的边,若不形成回路则将此边加入最小生成树。

function find(v:integer):integer; {返回顶点v所在的集合}
  var i:integer;
  begin
    i:=1;
    while (i0 do begin
      i:=find(e[q].v1);j:=find(e[q].v2);
      if i<>j then begin
        inc(tot,e[q].len);
        vset[i]:=vset[i]+vset[j];vset[j]:=[];
        dec(p);
      inc(q);
    writeln(tot);

2.最短路径
A.标号法求解单源点最短路径:

a:array[1..maxn,1..maxn] of integer; b:array[1..maxn] of integer; {b[i]指顶点i到源点的最短路径} mark:array[1..maxn] of boolean; procedure bhf; best,best_j:integer; begin fillchar(mark,sizeof(mark),false); mark[1]:=true; b[1]:=0;{1为源点} repeat best:=0; for i:=1 to n do If mark[i] then {对每一个已计算出最短路径的点} for j:=1 to n do if (not mark[j]) and (a[i,j]>0) then if (best=0) or (b[i]+a[i,j]0 then begin b[best_j]:=best;mark[best_j]:=true; until best=0; end;{bhf}

B.Floyed算法求解所有顶点对之间的最短路径:

procedure floyed;
  begin
    for I:=1 to n do
      for j:=1 to n do
      if a[I,j]>0 then p[I,j]:=I else p[I,j]:=0; {p[I,j]表示I到j的最短路径上j的前驱结点}
        for k:=1 to n do {枚举中间结点}
          for i:=1 to n do
            for j:=1 to n do
              if a[i,k]+a[j,k]

C. Dijkstra 算法:

a:array[1..maxn,1..maxn] of integer; b,pre:array[1..maxn] of integer; {pre[i]指最短路径上I的前驱结点} mark:array[1..maxn] of boolean; procedure dijkstra(v0:integer); begin fillchar(mark,sizeof(mark),false); for i:=1 to n do begin d[i]:=a[v0,i]; if d[i]<>0 then pre[i]:=v0 else pre[i]:=0; mark[v0]:=true; repeat {每循环一次加入一个离1集合最近的结点并调整其他结点的参数} min:=maxint; u:=0; {u记录离1集合最近的结点} for i:=1 to n do if (not mark[i]) and (d[i]0 then begin mark[u]:=true; for i:=1 to n do if (not mark[i]) and (a[u,i]+d[u]

3.计算图的传递闭包

Procedure Longlink;
    T:array[1..maxn,1..maxn] of boolean;
  Begin
    Fillchar(t,sizeof(t),false);
    For k:=1 to n do
      For I:=1 to n do
        For j:=1 to n do T[I,j]:=t[I,j] or (t[I,k] and t[k,j]);

4.无向图的连通分量
A.深度优先

procedure dfs ( now,color: integer);
  begin
    for i:=1 to n do
      if a[now,i] and c[i]=0 then begin {对结点I染色}
        c[i]:=color;
        dfs(I,color);

B 宽度优先(种子染色法)

5.关键路径
几个定义: 顶点1为源点,n为汇点。
a. 顶点事件最早发生时间Ve[j], Ve [j] = max{ Ve [j] + w[I,j] },其中Ve (1) = 0;
b. 顶点事件最晚发生时间 Vl[j], Vl [j] = min{ Vl[j] – w[I,j] },其中 Vl(n) = Ve(n);
c. 边活动最早开始时间 Ee[I], 若边I由表示,则Ee[I] = Ve[j];
d. 边活动最晚开始时间 El[I], 若边I由表示,则El[I] = Vl[k] – w[j,k];
若 Ee[j] = El[j] ,则活动j为关键活动,由关键活动组成的路径为关键路径。
求解方法:
a. 从源点起topsort,判断是否有回路并计算Ve;
b. 从汇点起topsort,求Vl;
c. 算Ee 和 El;

6.拓扑排序
找入度为0的点,删去与其相连的所有边,不断重复这一过程。
例 寻找一数列,其中任意连续p项之和为正,任意q 项之和为负,若不存在则输出NO.

7.回路问题
Euler回路(DFS)
定义:经过图的每条边仅一次的回路。(充要条件:图连同且无奇点)
Hamilton回路
定义:经过图的每个顶点仅一次的回路。
一笔画
充要条件:图连通且奇点个数为0个或2个。

9.判断图中是否有负权回路 Bellman-ford 算法
x[I],y[I],t[I]分别表示第I条边的起点,终点和权。共n个结点和m条边。

procedure bellman-ford
  begin
    for I:=0 to n-1 do d[I]:=+infinitive;
    d[0]:=0;
    for I:=1 to n-1 do
      for j:=1 to m do {枚举每一条边}
        if d[x[j]]+t[j]

10.第n最短路径问题
*第二最短路径:每举最短路径上的每条边,每次删除一条,然后求新图的最短路径,取这些路径中最短的一条即为第二最短路径。
*同理,第n最短路径可在求解第n-1最短路径的基础上求解。

三、背包问题

*部分背包问题可有贪心法求解:计算Pi/Wi
数据结构:
w[i]:第i个背包的重量;
p[i]:第i个背包的价值;

1.0-1背包: 每个背包只能使用一次或有限次(可转化为一次):
A.求最多可放入的重量。
NOIP2001 装箱问题
有一个箱子容量为v(正整数,o≤v≤20000),同时有n个物品(o≤n≤30),每个物品有一个体积 (正整数)。要求从 n 个物品中,任取若千个装入箱内,使箱子的剩余空间为最小。
l 搜索方法

procedure search(k,v:integer); {搜索第k个物品,剩余空间为v}
  var i,j:integer;
  begin
    if v=best then exit; {s[n]为前n个物品的重量和}
    if kw[k] then search(k+1,v-w[k]);
      search(k+1,v);

l DP
F[I,j]为前i个物品中选择若干个放入使其体积正好为j的标志,为布尔型。
实现:将最优化问题转化为判定性问题

f [I, j] = f [ i-1, j-w[i] ] (w[I]<=j)
  For I:=1 to n do
    For j:=w[I] to v do F[I,j]:=f[I-1,j-w[I]];
       {优化:当前状态只与前一阶段状态有关,可降至一维。}
  F[0]:=true;
  For I:=1 to n do begin
    F1:=f;
    For j:=w[I] to v do
      If f[j-w[I]] then f1[j]:=true;
    F:=f1;

B.求可以放入的最大价值。
F[I,j] 为容量为I时取前j个背包所能获得的最大价值。

F [i,j] = max { f [ i – w [ j ], j-1] + p [ j ], f[ i,j-1] }

C.求恰好装满的情况数。
DP:

Procedure update;
  var j,k:integer;
  begin
    c:=a;
    for j:=0 to n do
      if a[j]>0 then
    if j+now

2.可重复背包

A求最多可放入的重量。
F[I,j]为前i个物品中选择若干个放入使其体积正好为j的标志,为布尔型。
状态转移方程为

f[I,j] = f [ I-1, j – w[I]*k ] (k=1.. j div w[I])

B.求可以放入的最大价值。
USACO 1.2 Score Inflation
进行一次竞赛,总时间T固定,有若干种可选择的题目,每种题目可选入的数量不限,每种题目有一个ti(解答此题所需的时间)和一个si(解答此题所得的分数),现要选择若干题目,使解这些题的总时间在T以内的前提下,所得的总分最大,求最大的得分。
*易想到:

f[i,j] = max { f [i- k*w[j], j-1] + k*p[j] } (0<=k 其中f[i,j]表示容量为i时取前j种背包所能达到的最大值。
Begin
  FillChar(f,SizeOf(f),0);
  For i:=1 To M Do
    For j:=1 To N Do
      If i-problem[j].time>=0 Then
      Begin
        t:=problem[j].point+f[i-problem[j].time];
        If t>f[i] Then f[i]:=t;
  Writeln(f[M]);

C.求恰好装满的情况数。
Ahoi2001 Problem2
求自然数n本质不同的质数和的表达式的数目。
思路一,生成每个质数的系数的排列,在一一测试,这是通法。

procedure try(dep:integer);
  var i,j:integer;
  begin
    cal; {此过程计算当前系数的计算结果,now为结果}
    if now>n then exit; {剪枝}
    if dep=l+1 then begin {生成所有系数}
      if now=n then inc(tot);
      exit;
    for i:=0 to n div pr[dep] do begin
      xs[dep]:=i;
      try(dep+1);
      xs[dep]:=0;

思路二,递归搜索效率较高

procedure try(dep,rest:integer);
  var i,j,x:integer;
  begin
    if (rest

思路三:可使用动态规划求解
USACO1.2 money system
V个物品,背包容量为n,求放法总数。
转移方程:

Procedure update;
  var j,k:integer;
  begin
    c:=a;
    for j:=0 to n do
      if a[j]>0 then
        for k:=1 to n div now do
          if j+now*k

四、排序算法

A.快速排序:

procedure qsort(l,r:integer);
  var i,j,mid:integer;
  begin
    i:=l;j:=r; mid:=a[(l+r) div 2]; {将当前序列在中间位置的数定义为中间数}
    repeat
      while a[i]mid do dec(j);{在右半部分寻找比中间数小的数}
      if ij;

B.插入排序:

思路:当前a[1]..a[i-1]已排好序了,现要插入a[i]使a[1]..a[i]有序。

procedure insert_sort;
  var i,j:integer;
  begin
    for i:=2 to n do begin
      a[0]:=a[i];
      j:=i-1;
      while a[0]

C.选择排序:

procedure sort;
  var i,j,k:integer;
  begin
    for i:=1 to n-1 do 
      for j:=i+1 to n do
        if a[i]>a[j] then swap(a[i],a[j]);

D. 冒泡排序

procedure bubble_sort;
  var i,j,k:integer;
  begin
    for i:=1 to n-1 do
      for j:=n downto i+1 do
        if a[j]

E.堆排序:

procedure sift(i,m:integer);{调整以i为根的子树成为堆,m为结点总数}
  var k:integer;
  begin
    a[0]:=a[i]; k:=2*i;{在完全二叉树中结点i的左孩子为2*i,右孩子为2*i+1}
    while k

F. 归并排序

{a为序列表,tmp为辅助数组}
procedure merge(var a:listtype; p,q,r:integer);
{将已排序好的子序列a[p..q]与a[q+1..r]合并为有序的tmp[p..r]}
    I,j,t:integer;
    tmp:listtype;
  begin
    t:=p;i:=p;j:=q+1;{t为tmp指针,I,j分别为左右子序列的指针}
    while (tr) or (a[i]r then begin
      q:=(p+r-1) div 2;
      merge_sort (a,p,q);
      merge_sort (a,q+1,r);
      merge (a,p,q,r);
{main}
begin
  merge_sort(a,1,n);

G.基数排序
思想:对每个元素按从低位到高位对每一位进行一次排序

五、高精度计算

高精度数的定义:

hp=array[1..maxlen] of integer;

1.高精度加法

procedure plus ( a,b:hp; var c:hp);
  var i,len:integer;
  begin
    fillchar(c,sizeof(c),0);
    if a[0]>b[0] then len:=a[0] else len:=b[0];
    for i:=1 to len do begin
      inc(c[i],a[i]+b[i]);
      if c[i]>10 then begin dec(c[i],10); inc(c[i+1]); end; {进位}
    if c[len+1]>0 then inc(len);
    c[0]:=len;
  end;{plus}

2.高精度减法

procedure substract(a,b:hp;var c:hp);
  var i,len:integer;
  begin
    fillchar(c,sizeof(c),0);
    if a[0]>b[0] then len:=a[0] else len:=b[0];
    for i:=1 to len do begin
      inc(c[i],a[i]-b[i]);
      if c[i]1) and (c[len]=0) do dec(len);
      c[0]:=len;

3.高精度乘以低精度

procedure multiply(a:hp;b:longint;var c:hp);
  var i,len:integer;
  begin
    fillchar(c,sizeof(c),0);
    len:=a[0];
    for i:=1 to len do begin
      inc(c[i],a[i]*b);
      inc(c[i+1],(a[i]*b) div 10);
      c[i]:=c[i] mod 10;
    inc(len);
    while (c[len]>=10) do begin {处理最高位的进位}
      c[len+1]:=c[len] div 10;
      c[len]:=c[len] mod 10;
      inc(len);
    while (len>1) and (c[len]=0) do dec(len); {若不需进位则调整len}
    c[0]:=len;
  end;{multiply}

4.高精度乘以高精度

procedure high_multiply(a,b:hp; var c:hp}
  var i,j,len:integer;
  begin
    fillchar(c,sizeof(c),0);
    for i:=1 to a[0] do
      for j:=1 to b[0] do begin
        inc(c[i+j-1],a[i]*b[j]);
        inc(c[i+j],c[i+j-1] div 10);
        c[i+j-1]:=c[i+j-1] mod 10;
    len:=a[0]+b[0]+1;
    while (len>1) and (c[len]=0) do dec(len);
    c[0]:=len;

5.高精度除以低精度

procedure devide(a:hp;b:longint; var c:hp; var d:longint);
{c:=a div b; d:= a mod b}
var i,len:integer;
  begin
    fillchar(c,sizeof(c),0);
    len:=a[0]; d:=0;
    for i:=len downto 1 do begin
      d:=d*10+a[i];
      c[i]:=d div b;
      d:=d mod b;
  while (len>1) and (c[len]=0) then dec(len);
  c[0]:=len;

6.高精度除以高精度

procedure high_devide(a,b:hp; var c,d:hp);
    i,len:integer;
  begin
    fillchar(c,sizeof(c),0);
    fillchar(d,sizeof(d),0);
    len:=a[0];d[0]:=1;
    for i:=len downto 1 do begin
      multiply(d,10,d);
      d[1]:=a[i];
      while(compare(d,b)>=0) do {即d>=b} begin
        Subtract(d,b,d);
        inc(c[i]);
    while(len>1)and(c.s[len]=0) do dec(len);
    c.len:=len;

六、 树的遍历

1.已知前序中序求后序

procedure Solve(pre,mid:string);
  var i:integer;
  begin
    if (pre='''') or (mid='''') then exit;
    i:=pos(pre[1],mid);
    solve(copy(pre,2,i),copy(mid,1,i-1));
    solve(copy(pre,i+1,length(pre)-i),copy(mid,i+1,length(mid)-i));
    post:=post+pre[1]; {加上根,递归结束后post即为后序遍历}

2.已知中序后序求前序

procedure Solve(mid,post:string);
  var i:integer;
  begin
    if (mid='''') or (post='''') then exit;  
    i:=pos(post[length(post)],mid);
    pre:=pre+post[length(post)]; {加上根,递归结束后pre即为前序遍历}
    solve(copy(mid,1,I-1),copy(post,1,I-1));
    solve(copy(mid,I+1,length(mid)-I),copy(post,I,length(post)-i));

3.已知前序后序求中序的一种

function ok(s1,s2:string):boolean;
  var i,l:integer; p:boolean;
  begin
    ok:=true;
    l:=length(s1);
    for i:=1 to l do begin
      p:=false;
      for j:=1 to l do
        if s1[i]=s2[j] then p:=true;
      if not p then begin ok:=false;exit;end;
procedure solve(pre,post:string);
  var i:integer;
  begin
    if (pre='''') or (post='''') then exit;
    i:=0;
    repeat
      inc(i);
    until ok(copy(pre,2,i),copy(post,1,i));
    solve(copy(pre,2,i),copy(post,1,i));
    midstr:=midstr+pre[1];
    solve(copy(pre,i+2,length(pre)-i-1),copy(post,i+1,length(post)-i-1));

七 进制转换

1任意正整数进制间的互化
除n取余

2实数任意正整数进制间的互化
乘n取整

3负数进制:
设计一个程序,读入一个十进制数的基数和一个负进制数的基数,并将此十进制数转换为此负 进制下的数:-R∈{-2,-3,-4,….-20}

八 全排列与组合的生成

1.排列的生成:(1..n)

procedure solve(dep:integer);
    i:integer;
  begin
    if dep=n+1 then begin writeln(s);exit; end;
    for i:=1 to n do
      if not used[i] then begin
        s:=s+chr(i+ord(''0''));used[i]:=true;
        solve(dep+1);
        s:=copy(s,1,length(s)-1); used[i]:=false;

2.组合的生成(1..n中选取k个数的所有方案)

procedure solve(dep,pre:integer);
    i:integer;
  begin
    if dep=k+1 then begin writeln(s);exit; end;
    for i:=1 to n do
      if (not used[i]) and (i>pre) then begin
        s:=s+chr(i+ord(''0''));used[i]:=true;
        solve(dep+1,i);
        s:=copy(s,1,length(s)-1); used[i]:=false;

九.查找算法

1.折半查找

function binsearch(k:keytype):integer;
  var low,hig,mid:integer;
  begin
    low:=1;hig:=n;
    mid:=(low+hig) div 2;
    while (a[mid].key<>k) and (lowk then hig:=mid-1
        else low:=mid+1;
      mid:=(low+hig) div 2;
    if low>hig then mid:=0;
    binsearch:=mid;

2.树形查找

二叉排序树:每个结点的值都大于其左子树任一结点的值而小于其右子树任一结点的值。
查找

function treesrh(k:keytype):pointer;
  var q:pointer;
  begin
    q:=root;
    while (q<>nil) and (q^.key<>k) do

*会议问题
(1) n个活动每个活动有一个开始时间和一个结束时间,任一时刻仅一项活动进行,求满足活动数最多的情况。
解:按每项活动的结束时间进行排序,排在前面的优先满足。
(2)会议室空闲时间最少。
(3)每个客户有一个愿付的租金,求最大利润。
(4)共R间会议室,第i个客户需使用i间会议室,费用相同,求最大利润。

十一、回溯法框架

1. n皇后问题

procedure try(i:byte);
  var j:byte;
  begin
    if i=n+1 then begin print;exit;end;
    for j:=1 to n do
      if a[i] and b[j+i] and c[j-i] then begin
        x[i]:=j;
        a[j]:=false; b[j+i]:=false; c[j-i]:=false;
        try(i+1);
        a[j]:=true; b[i+j]:=true; c[j-i]:=true;

2.Hanoi Tower 汉诺塔

h(n)=2*h(n-1)+1
h(1)=1
初始所有铜片都在a柱上

procedure hanoi(n,a,b,c:byte); {将第n块铜片从a柱通过b柱移到c柱上}
  begin
    if n=0 then exit;
    hanoi(n-1,a,c,b); {将上面的n-1块从a柱通过c柱移到b柱上}
    write(n,’moved from’,a,’to’,c);
    hanoi(n-1,b,a,c);{ 将b上的n-1块从b柱通过a柱移到c柱上

初始铜片分布在3个柱上,给定目标柱goal
h[1..3,0..n]存放三个柱的状态,now与nowp存最大的不到位的铜片的柱号和编号,h[I,0]存第I个柱上的个数。

Procedure move(k,goal:integer); {将最大不到位的k移到目标柱goal上}
  Begin
    If k=0 then exit;
    For I:=1 to 3 do
      For j:=1 to han[I,0] do
        If h[I,j]=k then begin now:=I;nowp:=j; end; {找到k的位置}
    If now<>goal then begin {若未移到目标}
    Move(k-1,6-now-goal); {剩下的先移到没用的柱上}
    Writeln(k moved from now to goal);
    H[goal,h[goal,0]+1]:=h[now,nowp]; h[now,nowp]:=0;
    Inc(h[goal,0]); dec(h[now,0]);
    Move(k-1,goal); {剩下的移到目标上}

十二、DFS框架

NOIP2001 数的划分

procedure work(dep,pre,s:longint); {入口为work(1,1,n)}
{dep为当前试放的第dep个数,pre为前一次试放的数,s为当前剩余可分的总数}
  var j:longint;
  begin 
    if dep=n then begin
      if s>=pre then inc(r); exit; 
    for j:=pre to s div 2 do work(dep+1,j,s-j); 
procedure try(dep:integer);
  var i:integer;
  begin
    if dep=k then begin
      if tot>=a[dep-1] then inc(sum);
      exit;
    for i:=a[dep-1] to tot div 2 do begin
      a[dep]:=i; dec(tot,i); 
      try(dep+1);
      inc(tot,i);
  end;{try}

十三、BFS框架

IOI94 房间问题

head:=1; tail:=0;
while tail

十五、数据结构相关算法

1.链表的定位函数

loc(I:integer):pointer; {寻找链表中的第I个结点的指针}
procedure loc(L:linklist; I:integer):pointer;
    p:pointer;
    j:integer;
  begin
    p:=L.head; j:=0;
    if (I>=1) and (I

2.单链表的插入操作

procedure insert(L:linklist; I:integer; x:datatype);
  var p,q:pointer;
  begin
    p:=loc(L,I);
    new(q);
    q^.data:=x;
    q^.next:=p^.next;
    p^.next:=q;
    inc(L.len);

3.单链表的删除操作

procedure delete(L:linklist; I:integer);
  var p,q:pointer;
  begin
    p:=loc(L,I-1);
    q:=p^.next;
    p^.next:=q^.next;
    dispose(q);
    dec(L.len);

4.双链表的插入操作(插入新结点q)

p:=loc(L,I);
new(q);
q^.data:=x;
q^.pre:=p;
q^.next:=p^.next;
p^.next:=q;
q^.next^.pre:=q;

5.双链表的删除操作

p:=loc(L,I); {p为要删除的结点}
p^.pre^.next:=p^.next;
p^.next^.pre:=p^.pre;
dispose(p);
Posted on Categories Olympics in InformaticsLeave a comment on 基本算法

Some Online Judge Websites

USACO https://usaco.training/ (经典)

浙江大学 https://zoj.pintia.cn/

北京大学 http://poj.org/

VIJOS https://vijos.org/

同济大学 http://acm.tongji.edu.cn

天津大学 http://acm.tju.edu.cn/toj

哈工大 http://acm.hit.edu.cn/

吉林大学 http://acm.jlu.edu.cn

四川大学 http://acm.scu.edu.cn/soj/

汕头大学 http://acm.stu.edu.cn

中国科技大学 http://acm.ustc.edu.cn/ustcoj/

杭州电子科技大学 http://acm.hdu.edu.cn

湖南大学 http://acm.hnu.cn:8080/online

福州大学 http://acm.fzu.edu.cn

厦门大学 http://acm.xmu.edu.cn/JudgeOnline

华中科技大学 http://www.hustoj.org/

浙江工业大学 http://acm.zjut.edu.cn/onlinejudge/

香港信息学竞赛 HKOI http://judge.hkoi.org

UVA https://onlinejudge.org/ (题目很杂)

URAL https://acm.timus.ru (偏重数学)

SGU http://acm.sgu.ru

EL Judge http://acm.mipt.ru/judge/problems.pl

SPOJ https://pl.spoj.com/

E-OLIMP https://www.eolymp.com/

Recent Posts