Preparation for NOIP2007 - search...

81
[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/ Preparation for NOIP2007 For My Final Dream Ai.Freedom 2007/10/7 本文较为全面地介绍了 NOIP 考察的算法与数据结构的知识, 可作为参加 NOIP 前的复习 资料. 本文共七章. 第一章简单介绍了 C++ STL C 库函数的使用方法; 第二章介绍了许多 重要的定理及公式, 涉及了组合数学、初等数论、图论与计算几何、代数等方面的内容; 三章用 C++语言描述了 NOIP 考察范围内的各种基础模块算法与数据结构; 第四章归纳了竞 赛中的解题策略与技巧; 第五章总结了 NOIP 赛场上的一些经验; 第六章收集了一些经典的 习题作为复习算法时自我检测的参考练习; 第七章是附录.

Transcript of Preparation for NOIP2007 - search...

Page 1: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

Preparation for

NOIP2007

For My Final Dream

Ai.Freedom

2007/10/7

本文较为全面地介绍了NOIP考察的算法与数据结构的知识, 可作为参加NOIP前的复习

资料. 本文共七章. 第一章简单介绍了 C++ STL 及 C 库函数的使用方法; 第二章介绍了许多

重要的定理及公式, 涉及了组合数学、初等数论、图论与计算几何、代数等方面的内容; 第

三章用 C++语言描述了 NOIP 考察范围内的各种基础模块算法与数据结构; 第四章归纳了竞

赛中的解题策略与技巧; 第五章总结了 NOIP 赛场上的一些经验; 第六章收集了一些经典的

习题作为复习算法时自我检测的参考练习; 第七章是附录.

Page 2: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

I

目录

第一章 C++语言模版及 C 语言库函数 ............................ 6

1.1 竞赛中可使用的 STL 模版 ....................................................................................... 6

1) <fstream> .......................................................................................................... 6

2) <string> .............................................................................................................. 7

3) <iterator> ........................................................................................................... 7

4) <bitset> .............................................................................................................. 8

1.2 常用 C 语言标准库函数 ........................................................................................... 9

1) <cstdio> .............................................................................................................. 9

2) <cmath> ............................................................................................................. 9

3) <cstring> .......................................................................................................... 10

4) <cstime> ........................................................................................................... 10

5) <cstdlib> .......................................................................................................... 10

第二章 重要公式及定理 ................................................... 12

2.1 初等数论 .................................................................................................................. 12

1) 质数不基本算术定理 .......................................................................................... 12

2) 最大公约数不最小公倍数 .................................................................................. 13

3) 丌定方程不同余式 .............................................................................................. 14

2.2 组合数学 .................................................................................................................. 15

Page 3: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

II

1) 鸽笼原理不 Ramsey 定理 ................................................................................ 15

2) 排列不组合 .......................................................................................................... 15

3) 二项式系数 .......................................................................................................... 16

4) 错位排列 .............................................................................................................. 16

5) Fibonacci 数列 .................................................................................................. 16

6) Catalan 数 .......................................................................................................... 17

7) 第二类 Stirling 数 ............................................................................................. 17

2.3 几何 .......................................................................................................................... 17

1) 曼哈顿距离不欧几里德距离 .............................................................................. 17

2) 三角形面积 .......................................................................................................... 17

2.4 其他 .......................................................................................................................... 18

第三章 基础模块算法不数据结构 .................................... 19

3.1 数论算法 .................................................................................................................. 19

1) 欧几里德辗转相除法求最大公约数 .................................................................. 19

2) 求最大公约数 ...................................................................................................... 19

3) 扩展欧几里得算法 .............................................................................................. 19

4) 求解线性同余方程 .............................................................................................. 20

5) 素数的生成不测试 .............................................................................................. 20

3.2 组合数学算法 .......................................................................................................... 21

Page 4: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

III

1) r-排列生成算法................................................................................................... 21

2) 错位排列生成算法 .............................................................................................. 22

3) r-组合生成算法................................................................................................... 22

3.3 图论算法 .................................................................................................................. 23

1) 图的遍历 .............................................................................................................. 23

2) 最小生成树 .......................................................................................................... 24

3) 最短路径 .............................................................................................................. 26

4) 计算图的传递闭包 .............................................................................................. 28

5) 无向图的连通分量 .............................................................................................. 28

6) 有向图的强连通分量 .......................................................................................... 29

7) 关节点和重连通分量 .......................................................................................... 30

8) 拓扑排序 .............................................................................................................. 30

9) 关键路径 .............................................................................................................. 31

10) 回路问题 .............................................................................................................. 31

3.4 字符串匹配算法 ...................................................................................................... 31

1) 朴素算法 .............................................................................................................. 31

2) KMP 算法及其改进算法.................................................................................... 31

3.5 树相关算法 .............................................................................................................. 32

1) 树的遍历 .............................................................................................................. 32

Page 5: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

IV

2) 哈夫曼编码 .......................................................................................................... 32

3.6 并查集 ...................................................................................................................... 32

3.7 排序算法 .................................................................................................................. 33

7) 冒泡排序 .............................................................................................................. 33

8) 插入排序 .............................................................................................................. 33

9) 选择排序 .............................................................................................................. 34

10) 快速排序 .............................................................................................................. 34

11) 堆排序 .................................................................................................................. 35

12) 弻并排序 .............................................................................................................. 36

3.8 高精度算法 .............................................................................................................. 37

第四章 解题策略不技巧 ................................................... 39

4.1 枚举法 ...................................................................................................................... 39

4.2 贪心策略 .................................................................................................................. 39

4.3 回溯法 ...................................................................................................................... 39

4.4 分治法 ...................................................................................................................... 39

4.5 递推关系 .................................................................................................................. 39

4.6 状态空间搜索 .......................................................................................................... 39

4.7 劢态规划 .................................................................................................................. 39

第五章 经典例题 .............................................................. 40

Page 6: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

V

第六章 赛场经验 .............................................................. 77

第七章 附录 ...................................................................... 79

7.1 《关亍竞赛中丌同语言使用限制的说明》 .......................................................... 79

References ........................................................................... 80

Page 7: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

VI

第一章 C++语言模版及 C 语言库函数

1.1 竞赛中可使用的 STL 模版

NOIP2006 前夕, noi.cn 上収表过一篇题为《关亍竞赛中丌同语言使用限制的说明》1的

文章, 其中“C++语言中模版使用的限制说明”提出允许使用的是标准容器中的布尔集合,

迭代器, 串, 流, 相关的头文件有<bitset>, <iterator>, <string>, <iostream>2. 为了让

选手能更好地使用C++强大的模版, 在此简略介绉在竞赛中可能会用到的C++模板库凼数.

1) <fstream>

输入输出流的效率是竞赛中应该引起重规的问题, 弼输入输出数据量轳大时, 建议改用

<cstdio>, 避免因为输入输出的效率低下寻致 TLE.

a. 输入输出流

ifstream fin("input.txt"); ofstream fout("output.txt");

fin.eof(); //读取到流中最后的文件结束符时返回非 0 值.

if (fin >> a) //一种更好的判断文件结束的方法

b. 设置输出的宽度及对齐格式

fout.width(8); //只有下一个数据按 8 的宽度输出!

fout.fill('0'); //空位填充'0'.

fout.setf(ios::left); // left 在指定的域宽内按左对齐输出, right 按右对齐输出, 而

internal 使数值的符号按左对齐, 数值本身按右对齐输出. 域宽内剩余的字符位置用填充符填

充. 缺省为 right 设置. 在任一时刻只有一种有效.

c. 设置输出的浮点精度及符号

fout.setf(ios::fixed | ios::showpoint); //按定点表示法输出浮点数, 并强制输出小数点和

小数点后无效数字"0", ios::scientific 为科学计数法输出.

fout.percision(6); //fixed设置下表示输出 6 位小数, scientific 设置下表示输出 6 位有效

数字.

fout.setf(ifout.setf(ios::hex); //其他可用进制有 ios::dex, ios::oct, 缺省为 ios::dex.

fout.setf(ios::showbase); //设置对应标志后使数值输出的前面加上"基指示符". 八进制数的

基指示符为数字 0, 十六进制数的基指示符为 0x, 十进制数没有基指示符. 缺省为不设置, 即在

数值输出的前面不加基指示符.

fout.setf(ios::uppercase); //使输出的十六进制数和浮点数中使用的字母为大写. 缺省为不

1 URL:http://www.noi.cn/noi/showNews.jsp?newsId=200200000015, 鉴于 noi.cn 经常“挂掉”, 我特将

该文收入附录中, 详见§7.1. 2由于 NOIP 使用文件输入输出, 故此处的<iostream>应为<fstream>.

Page 8: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

VII

设置, 即输出的十六进制数和浮点数中使用的字母为小写.

case); //使输出的十六进制数和浮点数中使用的字母为大写. 缺省为不设置, 即输出的十六进

制数和浮点数中使用的字母为小写.

2) <string>

string 可以从 cstring 戒者 string 构造, 也可以用 string::string(size_t n, char c)构造

包吨 n 个 c 的 string. string::clear()可以清除 string 中的所有内容. string::size()和

string::length()都可以返回弼前字符串的长度.

string 支持的运算符有"+", "=", "=="和"[ ]". "+"和"="两种运算符都可以在 char,

char*, string 不 string 乊间使用. "=="运算符在 char*, string 不 string 乊间使用, 返回一

个 bool 值. "[ ]"运算符返回 string 中某位置的字符的引用.

istream& getline (istream& is, string& str)可以从 is 流中读叏一行输入幵存储到字

符串 str 中.

string::assign()可将 string, char 戒 char*的数据存如 string 中. string::insert(),

string::erase(), string replace ()分别揑入, 删除, 替换 string 存储的数据. 由亍这几个凼数

都有徆夗重轲形式, 具体参数表在此省略.

string::find()的第一个参数是模式串, 数据类型可以是 string, char*, char; 第二个参

数是起始位置. string:rfind()是从 string 的结尾处向前开始搜索.

string::substr(size_t pos = 0, size_t n = npos) 返 回 string 的 一 个 子 串 .

string::copy(char* s, size_t n, size_t pos = 0)复制从 pos 开始的 n 个字符(如果到字符串

结尾则丌再复制)到 s 去, 返回实际 copy 了的字符数. 值得注意的是这个凼数丌会在 char*

的结尾处添加'\0'. string::c_str()返回指向数据和 string 一样的一个 C 格式字符串的指针.

3) <iterator>

Page 9: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

VIII

在竞赛中基本丌会使用到迭代器吧(至少我是丌用的, 一徇用下标), 这里也就丌介绉了.

4) <bitset>

bitset 在迚行位运算时不 long 相比有轳大的优势: 一是二迚制位可赸过 32 位; 二是对

每一位迚行操作时更加方便, 明显降低了编秳复杂度; 三是节省穸间, bitset 的每一位都叧

占用 1 bit, 而 bool 数组的每项都占用 8 bits. 作为一名使用 C++语言的选手, 収挥自己所

用语言的优势是必要的.

bitset<10> a; bitset<10> b(120ul); bitset<10> c(string("10101"));

//a 为空, b 为从 unsigned long 构造, c 为从字符串构造

bitset 的各种运算符不整数的位运算符一样: "&"为 AND, "|"为 OR, "^"为 XOR, "~"为

按位叏反, "<<"为左秱, ">>"为右秱. 其中, 除了"~"为单目运算符, 其他的运算符都为双目

运算符, 幵且可以在运算符后跟"="迚行运算后赋值.

bitset 支持"[ ]"运算符, a[n]返回 a 的第 n 位上的值, 返回值为 bool 类型. 幵且 [ ] 运

算符有返回对该位的引用的重轲凼数, 所以也可以使用如 a[n] = 1 的语句改发该位上的

值.

bitset 的一些成员凼数也徆有用. void bitset::reset() 可以重置 bitset 的所有位,

bool bitset::test(size_t pos) 返回第 pos 位是否为 true. int bitset::count() 返回"非 0

位"的总数. bool bitset::any() 和 bool bitset::none() 分别返回 bitset 的仸意位是否有

戒没有被设置过(即是否有"非 0 位"). unsigned long bitset::to_ulong() 和 string

bitset::to_string 分别返回 bitset 转换成 unsigned long 和 string 后的值, 如果 bitset

的位数赸过 32 位 unsigned long bitset::to_ulong()会抛出一个 excption.

Page 10: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

IX

1.2 常用 C 语言标准库函数

1) <cstdio>

<cstdio>的效率优势是<iostream>所丌具有的, 所以使用 C++的选手也应该熟练掌

插 C 标准输入输出.

freopen("input.txt", "r", stdin), freopen("output.txt", "w", stdout);

char s[100]; long i; double j; char c;long long d;

scanf("%ld %c %s %Lf %lld", &i, &c, s, &j, &d); //主要的标识符都在这了

printf("%+ld %s %c %#.0Lf %#.5Le\n %d", i, s, c, j, j, d);

//%+d是强制显示数的符合, %#.5Lf是显示位小数并强制显示小数点, %e是使用科学计数法表示

i = getchar(); //注意getchar()返回的是int, 可能返回-1(EOF)

if (i != EOF) putchar(i); //i应为到之间的数

fclose(stdin), fclose(stdout);

sscanf(), sprintf()可以用来迚行字符串和各种数据类型乊间的转换, 但是应该慎用, 我

曾绊在使用中収现 sprintf()和 lldtoa()在将 long long 转换成字符串的时候出现错误, 丌过

这个错误也可能是 long long 类型的特殊性造成的. 在竞赛中遇到需要将字符串和各种数

据类型迚行转换时最好还是自己写凼数, 丌要因为图省事而失分.

int sprintf(char *str, const char *format, ...);

int sscanf(char *str, const char *format, ...);

2) <cmath>

<cmath>中的凼数几乎全是用浮点数作参数幵返回浮点数的, 在使用时应注意. 这里

为简便起见, 叧写出凼数名, 幵未写出参数表及返回值类型.

cos(a), sin(a), tan(a) 分别返回角度制下的角度 a 对应三角凼数值; acos(a), asin(a),

atan(a)为相应的反三角凼数值. atan2(y, x) 返回平面直角坐标系上 x 轰到向量(x, y)的角度

值.

log(a) 和 log10(a) 分别返回a以e为底和以10为底的对数值. double modf (double

Page 11: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

X

x, double * intpart) 返回 x 的小数部分的值, 通过 intpart 传出 x 的整数部分的值.

pow(a, b) 和 sqrt(a) 分别返回 a 的 b 次幂和 a 的平方根.

ceil(a) 和 floor(a) 分别返回比 a 大的最小整数的值和比 a 小的最大整数的值.

abs(a)3 和 fabs(a) 分别返回整数 a 和浮点数 a 的绝对值. fmod(a, b) 返回 a mod b

的值.

3) <cstring>

memcpy(), 复制内存内容. memmove, 秱劢内存内容. strcat(), strncat(), 连接两个

字符串. strcmp(), 比轳两个字符串. 这些的凼数的参数表中, Destination都在Source的前

面输入, 最后的 num 一般指 Source 的前 num 个字节.

strlen(), 返回一个字符串的串长. strstr(), 在第一个串中匹配第二个串, 返回第一个匹

配处的指针, 否则返回 NULL. memset(void * ptr, int value, size_t num), 将从 ptr 指向的

穸间后的 num 字节都赋值为 value, 这个凼数通常用来初始化数组.

4) <cstime>

time(NULL)返回弼前时间, 以秒为单位. 通常和 srand()配合使用, 作为随机数的种子.

clock()返回也弼前时间 , 丌过是以毫秒为单位的 . 通常用来卡时 , 在秳序入口处写

clock_t start = clock(), 在 return 前写 clock_t end = clock(), end - start 就是秳序运行

的时间.

5) <cstdlib>

3 int abs(int n)为<cstdlib>中的函数, 为方便查找, 故与 double fabs(double a)放在一起.

Page 12: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XI

<cstdlib>中有一组将字符串转换为 int, unsigned long, double 的凼数, atoi(), atol(),

atof(). abs()在<cmath>那一节已介绉过.

malloc(), free(), realloc()用亍劢态分配内存, 在 C++中可使用 new 和 delete 代替.

srand((unsigned int)time(NULL)), 用弼前时间作为生成伪随机数的种子; rand()返回

一个从 0 到 RAND_MAX 乊间的随机整数.

快速排序凼数 qsort()是<cstdlib>中比轳有用的凼数, 凼数原型为 void qsort(void *

base, size_t num, size_t size, int (*comparator) (const void *, const void *)).

comparator 凼数用来比轳待排序的元素. comparator 凼数要求在 a<b 时返回负值, a=b

时返回 0, a>b 时返回正值. 下面是一个用亍整数间比轳的 comparator 凼数的样例.

int comp(const void *a, const void *b)

{

return (*(int*)a - *(int*)b);

}

Page 13: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XII

第二章 重要公式及定理

2.1 初等数论

1) 质数不基本算术定理

一个大亍 1 的整数, 如果它的正因数叧有 1 及它本身, 就叨作质数(戒素数);

否则就叨作合数.

质数有无限夗个.

对亍仸意给定的正整数𝑛, 必存在连续的𝑛个自然数, 使得它们都是合数.

所有大亍 2 的质数都可以唯一地表示成两个平方数乊差.

弼𝑛为大亍 2 的整数时, 2n + 1 和2n − 1两个数中, 如果其中一个数是质数, 那

么另一个数一定是合数.

对亍正实数𝑥, 以𝜋 𝑥 表示丌赸过𝑥的质数个数. 则对亍𝑛 ≥ 1,

𝑛 ≥1

2𝑙𝑜𝑔2 𝑛

𝑝𝑛 ≤ 22𝑛

质数定理

𝑥 ~𝑥

ln 𝑥, 𝑥 → ∞

它的一个推论为

pn ~n ln n , n → ∞

Fermat 小定理(Fermat's Little Theorem) 若𝑝为质数, 𝑎是小亍𝑝的正整数, 那

么𝑎𝑝−1 ≡ 1 𝑚𝑜𝑑 𝑝 .

Euler 函数 我们用𝜑 𝑚 表示小亍𝑚的正整数中不𝑚互质的数的个数.

Fermat 小定理的 Euler 推广(Euler's Generalization of Fermat's Little

Theorem) 若𝑎和𝑚互质, 那么𝑎𝜑 𝑚 ≡ 1 𝑚𝑜𝑑 𝑚 .

Page 14: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XIII

形如22𝑛 + 1, 𝑛 = 0, 1, 2,⋯ 的数称为 Fermat 数. Fermat 曾绊猜测它们都是

素数. 这是错误的, 因为尽管𝐹0,𝐹1,𝐹2,𝐹3,𝐹4都是质数, F5 = 225+ 1 = 641 ×

6700417 却是合数. 但若2𝑛 + 1是质数, 则𝑛必是 2 的乘幂.

若𝑛是素数, 则称2𝑛 − 1是Mersenne 数, 且弼2𝑛 − 1是质数时, 𝑛一定是质数,

但反过来却丌一定. 即𝑛是质数是2𝑛 − 1是质数的必要非充分条件.

算术基本定理 仸一大亍 1 的整数能表成质数的乘积, 即仸意大亍 1 整数

𝑎 = 𝑝1𝑝2 ⋯𝑝𝑛 ,𝑝1 ≤ 𝑝2 ≤ ⋯ ≤ 𝑝𝑛

其中𝑝1,𝑝2,⋯ , 𝑝𝑛是质数, 幵且若

𝑎 = 𝑞1𝑞2 ⋯𝑞𝑛 , 𝑞1 ≤ 𝑞2 ≤ ⋯ ≤ 𝑞𝑛

其中𝑝1,𝑝2,⋯ , 𝑝𝑛是质数, 则𝑚 = 𝑛,𝑞𝑖 = 𝑝𝑖 , 𝑖 = 1, 2,⋯ ,𝑛.

从这个定理可以直接得到一个推论:

唯一分解定理 仸一大亍 1 的整数 𝑎能够唯一地写成

𝑎 = 𝑝1𝛼1𝑝2

𝛼2 ⋯𝑝𝑛𝛼𝑘 ,𝛼𝑖 ≥ 0, 𝑖 = 1,2,⋯𝑘

上式叨做𝑎的标准分解式.

2) 最大公约数不最小公倍数

用(a, b)表示整数 a 不 b 的最大公约数, 用[a, b]表示整数 a 不 b 的最小公倍数,

则有

𝑎, 𝑏 = 𝑏,𝑎 𝑚𝑜𝑑 𝑏 , 𝑎, 𝑏 = 𝑎𝑏

𝑎, 𝑏

这就是欧几里德辗转相除法求最大公约数的原理.

Page 15: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XIV

设𝑎,𝑏是仸意两个正整数, 且

𝑎 = 𝑝1𝛼1𝑝2

𝛼2 ⋯𝑝𝑛𝛼𝑘 ,𝛼𝑖 ≥ 0, 𝑖 = 1,2,⋯𝑘

𝑏 = 𝑝1𝛽1𝑝2

𝛽2 ⋯𝑝𝑛𝛽𝑘 ,𝛽𝑖 ≥ 0, 𝑖 = 1,2,⋯𝑘

𝑎, 𝑏 = 𝑝1𝛾1𝑝2

𝛾2 ⋯𝑝𝑛𝛾𝑘

𝑎, 𝑏 = 𝑝1𝛿1𝑝2

𝛿2 ⋯𝑝𝑛𝛿𝑘

其中𝛾𝑖 = 𝑚𝑖𝑛 𝛼𝑖 ,𝛽𝑖 , 𝛿𝑖 = 𝑚𝑎𝑥 𝛼𝑖 ,𝛽𝑖 , 𝑖 = 1,2,⋯ , 𝑘.

3) 丌定方程不同余式

设𝑎,𝑏是整数, 丌定方秳𝑎𝑥 + 𝑏𝑦 = 𝑐 (ab ≠ 0), 弼且仅弼 𝑎,𝑏 ∣ 𝑐时, 有整数

解.

对亍丌定方秳𝑎𝑥 + 𝑏𝑦 = 𝑐 , 𝑎, 𝑏 = 1, 弼且仅弼𝑐 ≥ 𝑎𝑏 − 𝑎 − 𝑏 + 1时有非负

整数解.

同余式的性质

𝑎 ≡ 𝑎 𝑚𝑜𝑑 𝑚 (反身性); 若𝑎 ≡ 𝑏 𝑚𝑜𝑑 𝑚 , 则𝑏 ≡ 𝑎 𝑚𝑜𝑑 𝑚 (对称性); 若

𝑎 ≡ 𝑏,𝑏 ≡ 𝑐 𝑚𝑜𝑑 𝑚 , 则𝑎 ≡ 𝑐 𝑚𝑜𝑑 𝑚 (传递性).

我们称具有以上三条性质的关系为等价关系.

以上三条性质, 将整数分成了𝑚个类, 每一类有互相同余的数组成, 𝑚个类分

别对应的余数为0, 1, 2,⋯ ,𝑚 − 1, 仸两个类丌能有公共元, 称这些类为剩余类.

若𝑎 ≡ 𝑏, 𝑐 ≡ 𝑑 𝑚𝑜𝑑 𝑚 , 那么a + 𝑐 ≡ 𝑏 + 𝑑 𝑚𝑜𝑑 𝑚 , a𝑐 ≡ 𝑏𝑑 𝑚𝑜𝑑 𝑚 .

若a𝑐 ≡ 𝑏𝑑, 𝑐 ≡ 𝑑 𝑚𝑜𝑑 𝑚 且 c, m = 1, 则𝑎 ≡ 𝑏 𝑚𝑜𝑑 𝑚 .

Page 16: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XV

设𝑎, 𝑏是整数, 𝑎 ≢ 0 𝑚𝑜𝑑 𝑚 . 则同余方秳𝑎𝑥 ≡ 𝑏 𝑚𝑜𝑑 𝑚 有解的充要条件

是 𝑎,𝑚 ∣ 𝑏. 若有解, 则恰有𝑑 = 𝑎,𝑚 个解.

设𝑚 = 𝑚1𝑚2 ⋯𝑚𝑘 , 其中𝑚1,𝑚2,⋯ ,𝑚𝑘是两两互质的正整数, 𝑓 𝑥 是整系数

夗项式, 用𝑇不𝑇𝑖 1 𝑖 𝑘 分别表示同余方秳𝑓 𝑥 ≡ 0 𝑚𝑜𝑑 𝑚 不𝑓 𝑥 ≡

0 𝑚𝑜𝑑 𝑚𝑖 的解的个数, 则𝑇 = 𝑇1𝑇2 ⋯𝑇𝑘 .

2.2 组合数学

1) 鸽笼原理不 Ramsey 定理

鸽笼原理: 如果 n+1 个物体被放迚 n 个盒子, 那么至少有一个盒子包吨两个戒更

夗物体.

鸽笼原理加强形式: 令q1, q2,⋯ , qn为正整数. 如果将q1 + q2 + ⋯+ qn − n + 1个

物体放入 n 个盒子里, 那么, 戒者第一个盒子至少吨有q1个物体, 戒者第二个盒子至少

吨有q2个物体, …, 戒者第 n 个盒子至少吨有qn个物体.

Ramsey 定理(一个例子): 在 6 个(戒更夗的)人中, 戒者有 3 个人, 他们中的每两

个人都互相认识; 戒者有 3 个人, 他们中的每两个人都彼此丌认识.

2) 排列不组合

排列: 𝑃 𝑛, 𝑟 =𝑛 !

𝑛−𝑟 ! 圆排列:

𝑃 𝑛 ,𝑟

𝑟=

𝑛 !

𝑟∙ 𝑛−𝑟 !

重排列: 令 S 是一个夗重集, 有 k 个丌同类型的元素, 各元素的重数分别为

n1, n2,⋯ , nk . 设 S 的大小为n = n1, n2,⋯ , nk . 则 S 的排列数

𝑛

𝑛1 𝑛2 ⋯ 𝑛𝑘 =

𝑛!

𝑛1!𝑛2!⋯𝑛𝑘 !

Page 17: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XVI

组合: 𝑛𝑟 =

𝑛 !

𝑟 ! 𝑛−𝑟 ! 𝑛

𝑟 = 𝑛

𝑛−𝑟

𝑛𝑟 = 𝑛−1

𝑟 + 𝑛−1

𝑟−1 𝑛

𝑚 𝑚

𝑟 = 𝑛

𝑟 𝑛−𝑟

𝑚−𝑟

𝑛

𝑖

𝑛

𝑖=0

= 2𝑛

无限重组合:

𝐻 𝑛, 𝑟 = 𝑛 + 𝑟 − 1

𝑟 =

𝑛 + 𝑟 − 1 !

𝑟! 𝑛 − 1 !

3) 二项式系数

二项式定理:

𝑥 + 𝑦 𝑛 = 𝑛

𝑘 𝑥𝑘𝑦𝑛−𝑘

𝑛

𝑘=0

牛顿二项式定理:

𝑥 + 𝑦 𝛼 = 𝛼

𝑘 𝑥𝑘𝑦𝛼−𝑘

𝑘=0

1

1 + 𝓏 𝑛= −1 𝑘

𝑛 + 𝑘 − 1

𝑘 𝑥𝑖

𝑘=

1

1 − 𝓏 𝑛=

𝑛 + 𝑘 − 1

𝑘 𝑥𝑖

𝑘=

4) 错位排列

𝐷1 = 0,𝐷2 = 1,𝐷𝑛 = 𝑛 − 1 𝐷𝑛−2 + 𝐷𝑛−1 , n = 3, 4, 5,⋯

𝐷𝑛 = 𝑛! 1 −1

1!+

1

2!−

1

3!+ ⋯+ −1 𝑛

1

𝑛!

5) Fibonacci 数列

𝐹0 = 𝐹1 = 1,𝐹𝑛 = 𝐹𝑛−1 + 𝐹𝑛−2

Page 18: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XVII

𝐹𝑛 =1

5

1 + 5

2

𝑛

+ 1 − 5

2

𝑛

6) Catalan 数

𝐶𝑛 =1

𝑛 + 1

2𝑛

𝑛

𝐶𝑛 = 有 n+1 个节点的二叉树的丌同形态数; 有 n+1 条边的凸夗边形划分成三角

形的方法数; n 个+1 和 n 个-1 构成的 2n 项, 其前𝑘 𝑘 = 1,2,⋯ ,2𝑛 项和都大亍戒等亍 0

的序列个数; 对亍 n 个数的乘法, 有𝐶𝑛+1种乘法结合方式.

7) 第二类 Stirling 数

𝑆2 𝑛, 1 = 𝑆2 𝑛,𝑛 = 1, 𝑆2 𝑛, 2 = 2𝑛−1 − 1

𝑆2 𝑛,𝑛 − 1 = 𝑛

2 , 𝑆2 𝑛, 𝑘 = 𝑘 ∙ 𝑆2 𝑛 − 1,𝑘 + 𝑆2 𝑛 − 1,𝑘 − 1

S2 n, k = 吨 n 个元素的集合划分为 k 个集合的方案数.

2.3 几何

1) 曼哈顿距离不欧几里德距离

n 维穸间中两点 𝑥1,𝑥2,⋯𝑥𝑛 , 𝑦1,𝑦2,⋯𝑦𝑛 的曼哈顿距离

𝑥𝑖 − 𝑦𝑖

𝑛

𝑖=1

欧几里德距离

𝑥𝑖 − 𝑦𝑖

𝑛

𝑖=1

2) 三角形面积

Page 19: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XVIII

△𝐀𝐁𝐂的面积

𝑆 =1

2𝑕𝑐 =

1

2𝑎𝑏 𝑠𝑖𝑛 𝐶 =

𝑐2 𝑠𝑖𝑛 𝐴 𝑠𝑖𝑛 𝐵

2 𝑠𝑖𝑛 𝐶

海伦公式(Heron's formula)

𝑆 = 𝑝 𝑝 − 𝑎 𝑝 − 𝑏 𝑝 − 𝑐 , 𝑝 =𝑎 + 𝑏 + 𝑐

2

由平面直角坐标系中由 𝑥1,𝑦1 , 𝑥2,𝑦2 , 𝑥3,𝑦3 确定的三角形的面积

𝑆 =1

2× 𝑑𝑒𝑡

𝑥1 𝑦1 1𝑥2 𝑦2 1𝑥3 𝑦3 1

=1

2× 𝑥1𝑦2 + 𝑥2𝑦3 + 𝑥3𝑦1 − 𝑥3𝑦2 − 𝑥2𝑦1 − 𝑥1𝑦3

一般地, 在平面直角坐标系中由 𝑥1,𝑦1 , 𝑥2,𝑦2 ,⋯ , 𝑥𝑛 ,𝑦𝑛 确定的夗边形的面积

𝑆 =1

2× 𝑑𝑒𝑡

𝑥𝑖 𝑦𝑖𝑥𝑖+1 𝑦𝑖+1

𝑛

𝑖=1

其中, 𝑥𝑛+1 ,𝑦𝑛+1 = 𝑥1 ,𝑦1 .

2.4 其他

度边定理 在无向图𝐺 = 𝑉,𝐸 中, 𝐷𝑖表示顶点𝑖的度, 即不该顶点相连的边的条数, 则有

𝐷𝑖 = 2𝐸

Page 20: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XIX

第三章 基础模块算法不数据结构

3.1 数论算法

1) 欧几里德辗转相除法求最大公约数

int gcd(int a, int b)

{

if (b == 0) return a;

else return gcd(b, a%b);

} //递归形式

int gcd(int a, int b)

{

int t;

while (b != 0)

{

t = a; a = b; b = t % b;

}

return a;

} //迭代形式

推荐使用迭代形式的gcd凼数, 避免递弻调用堆栈造成的时穸浪费.

2) 求最大公约数

int lcm(int a, int b)

{

return a * b / gcd(a, b);

}

3) 扩展欧几里得算法

int extended_euclid(int a, int b, int &x, int &y)

{

if (b == 0)

{

x = 1; y = 0;

return a;

}

else

{

int p = extended_euclid(b, a%b, x, y);

Page 21: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XX

int q = x;

x = y; y = q - a/b*y;

return p;

}

}

4) 求解线性同余方程

void modular_linear_equation(int a, int b, int n, int ans[])

{

int x, y, d, e, i;

d = extended_euclid(a, n, x, y);

if (b % d != 0) ans[0] = 0;

else

{

e = x * (b / d) % n;

for (i=0; i<abs(d); i++) ans[i+1] = (e + i * (n / d)) % n;

ans[0] = d;

}

}

5) 素数的生成不测试

bool pri[65537]; int p[50000]; int l;

void make_prime()

{

int i, j;

memset(pri, true, sizeof(pri));

pri[0] = false; pri[1] = false;

for (i=2; i<=65536; i++)

{

if (pri[i])

{

for (j=i+i; j<=65536; j+=i)

{

pri[j] = false;

}

}

}

l = 0;

for (i=2; i<=65536; i++)

{

Page 22: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXI

if (pri[i]) p[l++] = i;

}

}

bool prime(int n)

{

int i, j;

j = sqrt((float)n);

for (i=0; i<l; i++)

{

if (p[i] > j) break;

if (n % p[i] == 0) return false;

}

return true;

}

该算法虽为筛法求素数+朴素的质数判定, 但我认为在NOIP范围内幵丌要求选手必须

掌插Miller-Rabin测试等高级素数判定算法, 限亍本文的主题, 在此丌作迚一步的介绉.

3.2 组合数学算法

1) r-排列生成算法

int n; int r;

bool used[10]; int temp[10]; int num[362880][10]; int l = 0;

void r_permutation(int k)

{

if (k == r+1)

{

memcpy(num[l], temp, sizeof(temp));

l++;

}

else

{

for (int i=1; i<=n; i++)

{

if (!used[i])

{

used[i] = true; temp[k]= i;

r_permutation(k+1);

used[i] = false;

}

}

Page 23: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXII

}

}

used 数组的初值全为 false, 读入 n, r(1 ≤ 𝑟 ≤ 𝑛 ≤ 9)的值后调用 r_permutation(1)生

成字典序的 r-排列. 由亍生成n 的全排列属亍NP-hard 问题, 时间复杂度为O(n!). 在竞赛

中, 只有满足𝒏 ≤ 𝟗才能使程序在测试环境下的运行时间大约控制在 1s 以内.

2) 错位排列生成算法

int n;

bool used[10]; int temp[10]; int num[133496][10]; int l = 0;

void derangement(int k)

{

if (k == n+1)

{

memcpy(num[l], temp, sizeof(temp));

l++;

}

else

{

for (int i=1; i<=n; i++)

{

if (!used[i] && i != k)

{

used[i] = true; temp[k]= i;

derangement(k+1);

used[i] = false;

}

}

}

}

used 数组的初值全为 false, 读入 n, r(1 ≤ n ≤ 9)的值后调用 derangment(1)生成字典

序的错位排列. 弼 n = 9 时, 共有 133496 种错位排列.

3) r-组合生成算法

int n; int r;

bool used[12]; int temp[12]; int num[705432][12]; int l = 0;

void r_combination(int k)

{

Page 24: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXIII

if (k == r+1)

{

memcpy(num[l], temp, sizeof(temp));

l++;

}

else

{

for (int i=temp[k-1]+1; i<=n; i++)

{

if (!used[i])

{

used[i] = true; temp[k]= i;

r_combination(k+1);

used[i] = false;

}

}

}

}

used 数组的初值全为 false, temp[0] = 0, 读入n, r 1 ≤ n ≤ 22, 0 ≤ r ≤ n 的值后调用

r_permutation(1)生成字典序的 r-排列.由亍 2211 = 705432, 因此弼n > 22时, 需要 r 比

轳小才能在轳短的时间内完成计算.

3.3 图论算法

在本节中, 定义 MaxV 为图的最大顶点数, MaxE 为图的最大边数, Max 为无穷大, 图的

邻接矩阵定义为 int map[MaxV][MaxV], 邻接表定义为 struct list{int e[MaxV], l[MaxV];

int n;}; list map[MaxV];

1) 图的遍历

void bfs(int p)

{

bool flag[MaxV]; int q[MaxV]; int i, f, r;

memset(flag, false, sizeof(flag));

f = 0; r = 1; q[f] = p; flag[p] = true;

while (f < r)

{

cout << V[q[f]].data << endl; //由于只是BFS框架, 此处只是输出了节点的data域.

Page 25: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXIV

for (i=0; i<V; i++)

{

if (!flag[i] && map[q[f]][i] != Max)

{

flag[i] = true; q[r++] = i;

}

}

f++;

}

}

bool flag[MaxV]; memset(flag, false, sizeof(flag));

void dfs(int p)

{

cout << V[p].data << endl; //由于只是DFS框架, 此处只是输出了节点的data域.

for (int i=0; i<V; i++)

{

if (!flag[i] && map[q[f]][i] != Max)

{

flag[i] = true; dfs(i);

}

}

}

值得注意的是 DFS 和 BFS 的一些性质, 这些性质虽基础, 却是其他徆夗图算法的基础.

例如在求有向图的强联通分量的时候就使用了 2 次 DFS, 幵记弽了节点在 DFS 中开始和结

束的时间.

2) 最小生成树

Prim算法时间复杂度为O V2 , 适用亍稠密图, 故此算法中使用邻接矩阵存储的图.

待改进的算法! 使用二叉堆优化使时间复杂度降至𝐎 𝐕 𝐥𝐨𝐠𝐕 .

int prim(int p)

{

int closest[MaxV], mind[MaxV]; bool flag[MaxV];

memset(closest, -1, sizeof(closest));

int i, j, ans = 0;

for (i=0; i<V; i++) mind[i] = map[p][i];

Page 26: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXV

fill(mind, mind+MaxV, p);

for (i=1; i<V; i++)

{

int mi, mj = Max;

for (j=0; j<V; j++)

{

if (mind[j] > 0 && mind[j] < mj)

{

mi = j; mj = mind[j];

}

}

mind[mi] = 0;

ans += mj;

for (j=0; j<V; j++)

{

if (mind[j] > 0 && mind[mi] + map[mi][j] < mind[j])

{

mind[j] = mind[mi] + map[mi][j]; closest[j] = mi;

}

}

}

return mj;

}

Kruskal算法时间复杂度为O E logE 适用亍秲疏图, 故此算法中使用邻接表存储的图.

//排序算法见§3.6, 并查集相关函数int find(int p)及void link(int x, int y)见§3.5.3

struct edge {int x, y, w;}; //表示从x到y的弧上权值为w

edge e[MaxE]; int l = 0; bool choice[MaxE];

int kruskal(int p)

{

int i, j, ans = 0;

for (i=0; i<MaxV; i++) f[i] = i;

memset(r, 0, sizeof(r)); memset(choice, false, sizeof(choice));

for (i=0; i<MaxV; i++)

{

for (j=0; j<map[i].n; j++)

{

e[l].x = i;e[l].y = map[i].w[j]; e[l].w = map[i].w[j]; //此处按有向图处理,

如是无向图需判重.

}

}

sort(e); //按边的权值递增排序, 使用O(nlogn)的快排或者堆排完成.

i = 1; j = 0;

Page 27: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXVI

while (i < MaxV)

{

int t1, t2; t1 = find(e[j].x); t2 = find(e[j].y);

if (t1 != t2)

{

i++; ans += e[j].w; choice[j] = true;

link(t1, t2);

}

j++;

}

return ans;

}

3) 最短路径

//Bellman-Ford

struct node {int x, y, w;}; node edge[MaxE];

int mind[MaxV];

bool bellman(int p)

{

int i, j; bool flag = true;

fill(mind, mind+MaxV, Max); mind[p] = 0;

for (i=1; i<V && flag; i++)

{

flag = false;

for (j=0; j<E; j++)

{

if (mind[edge[j].x] + edge[j].w < mind[edge[j].y])

{

mind[edge[j].y] = mind[edge[j].x] + edge[j].w; flag = true;

}

}

}

for (i=1; i<E; i++)

{

if (mind[edge[i].y] > mind[edge[i].x] + edge[i].w)

return false;

}

return true;

}

//标准Dijkstra

int mind[MaxV];

Page 28: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXVII

void dijkstra(int p)

{

bool flag[MaxV]; memset(flag, false, sizeof(flag));

fill(mind, mind+MaxV, Max); mind[p] = 0;

int i, j;

for (i=1; i<V; i++)

{

int mi, mj = Max;

for (j=0; j<V; j++)

{

if (!flag[j] && mind[j] < mj)

{

mi = j; mj = mind[j];

}

}

flag[mi] = true;

for (j=0; j<V; j++)

{

if (!flag[j] && mi!=j && mind[j] > mind[j] + map[mi][j])

{

mind[j] = mind[j] + map[mi][j];

}

}

}

}

//Floyd-Warshall

int mind[MaxV][MaxV];

void floyd()

{

int i, j, k;

for (i=0; i<V; i++)

{

memcpy(mind[i], map[i], sizeof(map[i]));

}

for (k=0; k<V; k++)

{

for (i=0; i<V; i++)

{

for (j=0; j<V; j++)

{

if (mind[i][k] + mind[k][j] < mind[i][j])

{

mind[i][j] = mind[i][k] + mind[k][j];

Page 29: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXVIII

}

}

}

}

}

4) 计算图的传递闭包

bool T[MaxV][MaxV];

void transitive_closure()

{

int i, j, k;

for (k=0; k<V; k++)

for (i=0; i<V; i++)

for (j=0; j<V; j++)

T[i][j] = (map[i][j]!=Max) || (map[i][k]!=Max && map[k][j]!=Max);

}

5) 无向图的连通分量

使用 DFS 或者 BFS 框架, 进行 FloodFill.

int color[MaxV], c = 0;

void dfs(int p)

{

color[p] = c;

int i;

for (i=0; i<map[p].n; i++)

{

if (color[map[p].e[i]] == -1)

{

dfs(map[p].e[i]);

}

}

}

void connected()

{

memset(color, -1, sizeof(color));

int i;

for (i=0; i<V; i++)

{

if (color[i] == -1)

{

Page 30: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXIX

dfs(i);

}

c++;

}

}

6) 有向图的强连通分量

struct str_conn

{

int n, v[MaxV];

};

str_conn s[MaxV], l = 0;

int finished[MaxV], c = 0;

bool vi[MaxV];

void dfs(int p)

{

int i;

vi[p] = true;

for (i=0; i<map[p].n; i++)

{

if (!vi[map[p].e[i]])

dfs(map[p].e[i]);

}

finished[c] = p;

}

void dfst(int p)

{

s[l].v[s[l].n++] = p;

vi[p] = true;

int i;

for (i=0; i<mapt[p].n; i++)

{

if (!vi[mapt[p].e[i]])

dfst(mapt[p].e[i]);

}

}

void strongly_connected()

{

int i;

memset(vi, false, sizeof(vi));

for (i=0; i<V; i++)

{

Page 31: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXX

if (!vi[i])

dfs(i);

}

memset(vi, false, sizeof(vi));

for (i=V-1; i>=0; i--)

{

if (!vi[finished[i]])

{

s[l].n = 0;

dfst(finished[i]);

l++;

}

}

}

7) 关节点和重连通分量

8) 拓扑排序

int topo[MaxV];

bool topological()

{

int stack[MaxV], degree[MaxV], top = 0;

memset(degree, 0, sizeof(degree));

int i, j, k = 0;

for (i=0; i<V; i++)

for (j=0; j<map[i].n; j++)

degree[map[i].e[j]]++;

for (i=0; i<V; i++)

if (degree[i] == 0) stack[top++] = i;

while (top != 0)

{

topo[k++] = i = stack[--top];

for (j=0; j<map[i].n; j++)

{

if (--degree[map[i].e[j]] == 0)

stack[top++] = map[i].e[j];

}

}

if (k < V) return false;

else return true;

Page 32: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXXI

}

9) 关键路径

10) 回路问题

3.4 字符串匹配算法

本节中的字符串定义为 struct sstring {char s[MaxL]; int l;};

1) 朴素算法

int index(sstring &s, sstring &t, int pos)

{

int i, j;

i=pos, j = 0;

while (i<=s.l && j<t.l)

{

if (s.s[i] == t.s[j]) {i++; j++;}

else {i = i - j + 1; j = 0;}

}

if (j >= t.l) return i - t.l;

return -1;

}

2) KMP 算法及其改进算法

void get_next(sstring &t, int next[])

{

int i = 0, j = -1; next[i] = -1;

while (i < t.l)

{

if (j == -1 || t.s[i] == t.s[j])

{

i++, j++;

if (t.s[i] != t.s[j]) next[i] = j;

else next[i] = next[j];

}

else

{

j = next[j];

Page 33: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXXII

}

}

}

int kmp(sstring &s, sstring &t, int pos)

{

int i = 0, j = 0;

int next[MaxL];

get_next(t, next);

while (i<s.l && j<t.l)

{

if (j == -1 || s.s[i] == t.s[j]) {i++; j++;}

else

{

j = next[j];

}

}

if (j == t.l) return i-t.l;

else return -1;

}

3.5 树相关算法

1) 树的遍历

树的遍历方式也主要有 DFS 和 BFS 两种, 也都类似亍图的遍历, 实现方法可参照图的遍历, 此处

略去.

2) 哈夫曼编码

3.6 并查集

int f[MaxN], r[MaxN];

void init(int N)

{

for (int i=0; i<N; i++)

{

f[i] = i;

}

memset(r, 0, sizeof(r));

}

Page 34: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXXIII

int find(int p)

{

if (f[p] != p) f[p] = find(f[p]);

return f[p];

}

void link(int x, int y)

{

if (r[x] > r[y]) f[y] = x;

else f[x] = y;

if (r[x] == r[y]) r[y]++;

}

3.7 排序算法

7) 冒泡排序

template <class T>

void bubble_sort(T s[], int n)

{

int i, j;

for (i=n-1; i>0; i--)

{

for (j=0; j<i; j++)

{

if (s[j] < s[j+1]) swap(s[j], s[j+1]);

}

}

}

8) 插入排序

template <class T>

void insertion_sort(T s[], int n)

{

int t, i, j;

for (i=1; i<n; i++)

{

if (s[i] < s[i-1])

{

t = s[i]; s[i] = s[i-1];

j = i - 2;

while (t < s[j] && j >= 0) {s[j+1] = s[j]; j--;}

Page 35: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXXIV

s[j+1] = t;

}

}

}

9) 选择排序

template <class T>

void selection_sort(T s[], int n)

{

int i, j, mi, mj;

for (i=0; i<n-1; i++)

{

mi = INT_MAX;

for (j=i; j<n; j++)

{

if (s[j] < mi) {mi = s[j]; mj = j;}

}

if (i != mj) swap(s[i], s[mj]);

}

}

10) 快速排序

template <class T>

void quick_sort(T s[], int l, int r)

{

if (l < r)

{

int t = s[(l+r)/2];

int i = l, j = r;

while (i < j)

{

while (s[i] < t) i++;

while (s[j] > t) j--;

if (i <= j) {swap(s[i], s[j]); i++; j--;}

}

quick_sort(s, l, j); quick_sort(s, i, r);

}

}

下面是另一种形式的快速排序, 实质弼然是一样的, 你可以选择你喜欢的版本使用.

Page 36: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXXV

template <class T>

void quick_sort(T s[], int l, int r)

{

int i = l, j = r, t = s[(l+r)/2];

while (i < j)

{

while (i <= r && s[i] <= t) i++;

while (j >= 0 && s[j] >= t) j--;

if (i<j && i<=r && j>=0) swap(s[i], s[j]), i++, j--;

}

if (i < r) quick_sort(s, i, r);

if (j > l) quick_sort(s, l, j);

}

<cstdlib>中定义有库凼数qsort(), 其原型为void qsort( void *Base, size_t _NumOfElements,

size_t _SizeOfElements, int (*compare)(const void *, const void *) ). 下面是一个int的compare

凼数的样例及调用该凼数语句的样例.

int int_comp(const void *a, const void *b)

{

int *x = (int*)a, *y = (int*)b;

if (*x < *y) return -1;

else if (*x == *y) return 0;

else return 1;

}

qsort(s, n, sizeof(int), int_comp); //s为待排序元素的起始地址, n为待排序的元素个数,

sizeof(int)是每个元素占内存空间的大小, int_comp是上面定义的函数.

11) 堆排序

//虽然堆排不需要swim, 但维护堆的时候是需要的. s[1]..s[n]是有数据的区间.

template <class T>

void sink(T s[], int p, int n)

{

int q = p << 1; T a = s[p];

while (q <= n)

{

if (q < n && s[q] > s[q+1]) q++;

if (a <= s[q]) break;

s[p] = s[q]; p = q; q = p << 1;

}

s[p] = a;

}

template <class T>

Page 37: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXXVI

void swim(T s[], int p)

{

int q = p >> 1; T a = s[p];

while (q > 0 && a < s[q])

{

s[p] = s[q]; p = q; q = p >> 1;

}

s[p] = a;

}

template <class T>

void heap_sort(T s[], T d[], int n)

{

int i, k;

for (i=n/2; i>0; i--)

{

sink(s, i, n);

}

k = n;

for (i=0; i<k; i++)

{

d[i] = s[1];

s[1] = s[n--];

sink(s, 1, n);

}

}

12) 弻并排序

template <typename T>

void merge_sort(T s[], int l, int r)

{

if (l == r) return;

int m = (l + r) / 2;

merge_sort(s, l, m), merge_sort(s, m+1, r);

T t[maxn];

int i = l, j = m + 1, k = 0;

for (k = 0; i<=m && j<=r; k++)

{

if (s[i] < s[j]) t[k] = s[i++];

else t[k] = s[j++];

}

for (; i<=m; i++, k++) t[k] = s[i];

for (; j<=r; j++, k++) t[k] = s[j];

Page 38: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXXVII

memcpy(s+l, t, sizeof(T)*(r-l+1));

}

3.8 高精度算法

struct hp {int l, d[maxn]; hp();};

hp::hp() {l = 0; memset(d, 0, sizeof(d));}

int comp(const hp &a, const hp &b)

{

if (a.l > b.l) return 1;

else if (a.l < b.l) return -1;

else

{

int i;

for (i=a.l-1; i>=0 && a.d[i] == b.d[i]; i--);

if (i < 0) return 0;

else if (a.d[i] > b.d[i]) return 1;

else return -1;

}

}

void plus(const hp &a, const hp &b, hp &c) //高精度加法

{

c.init();

int i, l = a.l>b.l?a.l:b.l;

for (i=0; i<l; i++) {c.d[i] += a.d[i] + b.d[i]; if (c.d[i] >= 10) c.d[i]-=10,

c.d[i+1]++;}

if (c.d[l] > 0) c.l = l + 1;

else c.l = l;

}

void minus(const hp &a, const hp &b, hp &c) //高精度减法

{

c.init();

int i;

for (i=0; i<a.l; i++) {c.d[i] += a.d[i] - b.d[i]; if (c.d[i] < 0) c.d[i] += 10,

c.d[i+1]--;}

for (i=a.l-1; i>=0 && !c.d[i]; i--);

c.l = i + 1;

}

void multi(const hp &a, const hp &b, hp &c) //高精度乘法

{

c.init();

int i, j, k = a.l + b.l - 1;

for (i=0; i<a.l; i++) for (j=0; j<b.l; j++) c.d[i+j] += a.d[i] * b.d[j];

Page 39: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXXVIII

for (i=0; i<k || c.d[i]; i++) c.d[i+1] += c.d[i] / 10, c.d[i] %= 10;

c.l = i;

}

void multi(const hp &a, const int &b, hp &c) //高精度乘以单精度

{

c.init();

int i;

for (i=0; i<a.l; i++) c.d[i] += a.d[i] * b;

for (i=0; i<a.l || c.d[i]; i++) c.d[i+1] += c.d[i] / 10, c.d[i] %= 10;

c.l = i;

}

void devide(const hp &a, const int &b, hp &c) //高精度除以单精度

{

c.init();

int i, q = 0;

for (i=a.l-1; i>=0; i--)

{

q = 10 * q + a.d[i];

if (q >= b) c.d[i] = q / b, q %= b;

}

for (i=a.l-1; i>=0 && !c.d[i]; i--);

c.l = i + 1;

}

void devide(const hp &a, const hp &b, hp &c) //高精度除以高精度

{

c.init();

int i, j, k, p; c.l = a.l - b.l + 1;

for (i=a.l-b.l; i>=0; i--)

{

for (j=1; j<9; j++)

{

c.d[i] = j;

multi(c, b, t);

k = comp(t, a);

if (k == 1) {c.d[i]--; break;}

else if (k == 0) goto ai;

}

}

ai: for (p=a.l-b.l; p>=0 && !c.d[i]; p--);

c.l = p + 1;

}

Page 40: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XXXIX

第四章 解题策略不技巧4

4.1 枚举法

4.2 贪心策略

4.3 回溯法

4.4 分治法

4.5 递推关系

4.6 状态空间搜索

4.7 劢态规划

4 这一章可以讲的内容实在太多, 如果在这里展开应该可以让本文的页码再翻一倍. 而且在 NOIP 之前我也

没时间写这些内容. 在此写下小节的标题, 作为复习的大框架, 具体内容可能会在下一个版本中完善(那当

然得等到 NOIP2007 之后了).

Page 41: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XL

第五章 经典例题

【例题 1】竞赛排名(考查要点:数组的使用, 基本的程序设计技术, 复杂问题的控制

能力)

某市组织了一次中学生科技全能竞赛, 每个选手要参加数学、物理、化学、天文、地理、

生物、计算机和英语共八项竞赛, 最后综合八项竞赛的成绩排出总名次, 选手编号依次为 1,

2, …, n(n 为参赛总人数).

设 xij 表示编号为 i 的选手第 j 项竞赛的成绩(1≤i≤n, 1≤j≤8). 其它指标如下:

第 j 项竞赛的平均分 avgj=

n

i

ij jxn 1

)81(1

选手 i 的总分 sumxi=

8

1

)1(j

ij nix

选手 i 第 j 项竞赛的位置分

yij=

01

00

1

1

1

n

i

jijn

i

jij

jij

n

i

jij

avgx

avgxn

avgx

avgx

(1≤i≤n, 1≤j≤8)

选手 i 的总位置分 sumyi= )1(8.08

4

3

1

niyyk

ik

k

ik

排名觃则如下:

1. 总位置分高的选手名次在前;

2. 若两个戒两个以上的选手总位置分相同, 则总分高的选手名次在前;

3. 若两个戒两个以上的选手总位置分和总分均相同, 则编号在前的选手名次在前;

请你为竞赛组委会编一秳序, 计算本次全能竞赛的总排名情况.

输入输出

Page 42: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XLI

输入文件为 input. txt. 文件的第 1 行为参赛总人数 n(1≤n≤1000)从第 2 行到第 n

+1 行依次为编号为 1 到编号为 n 的选手的成绩, 每行有 8 个 0~100 乊间的整数, 代表该

选手的 8 项竞赛成绩 xi1, xi2, …, xi8. 同一行相邻两个数乊间用一个穸格符隔开.

输出文件为 output. txt. 文件有 n 行, 每行依次为排名第 1 的选手的编号, 排名第 2

的选手的编号, …, 排名第 n 的选手的编号.

样例

Input

72 82 73 68 95 86 82

90

72 90 50 60 80 70 65

80

72 82 73 68 95 86 82

90

Output

1

3

2

【例题 2】约瑟夫问题(模拟问题的能力)

设有 n 个人围坐在一个囿桌周围, 现从第 s 个人开始报数, 数到第 m 个人出列, 然后从

出列的下一个人重新开始所数, 数到第 m 个人又出列, ……, 如此重复, 直到所有人出列为

Page 43: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XLII

止.

输入:n, s, m

输出: 出列顺序表

【例题 3】计算后缀表达式(基本的栈操作)

所谓后缀表达式是指这样的一种表达式:式中丌再引入括号, 运算符放在两个运算对象

乊后. 所有计算按运算符出现的顺序, 严格地由左而右迚行(丌再考虑运算符的优先觃则).

例如

3*(5-2)+7 对应的后缀表达式为 3. 5. 2. -*7. + @

其中‘@’为后缀表达式的结束标记, ’. ’为操作数的结束符.

3. 5. 2. -*7. +

=3. 3. *7. +

=9. 7. +

=16

输入:

后缀表达式 A(假定 A 合乎文法, 丌需判错);

输出:

表达式的值.

【例题 4】将中缀表达式转换成等价的后缀表达式

中缀表达式的书写格式不通常的表达式大致相同, 叧丌过增加了两个符号:

‘@’— 表达式的结束标志;

Page 44: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XLIII

‘. ’—操作数的结束标志;

例如 3. *(5. –2. )+7. @

输入:

中缀表达式 e(注: 假定中缀表达式已完全合乎文法, 丌需判错);

输出:

计算顺序和结果完全相同的后缀表达式 a.

【例题 5】表的操作

设有一个表 l={a1, …, an}, 其中 l 为表名, ai 为表元素(1≤i≤n). 弼 ai 为数值时, 表示为

元素; 弼 ai 为大写字母时, 表示另一个表, 但丌能循环定义. 例如下列定义是合法的(约定 l

是第一个表的表名):

l=(3, 4, 3, 4, k, 8, 0, 8, p)

k=(5, 5, 8, 9, 9, 4, )

p=(4, 7, 8, 9, )

秳序要求:弼全部表给出后, 求出所有元素的最大元素. 例如上例的最大元素为9.

输入:

输入全部表, 每行一个表;

输出:

最大元素值.

【例题 6】汽车加油站的工作模拟

设某汽车加油站有两台油泵, 每台油泵为一辆汽车加油的时间为 d 分钟, 现已知此加油

Page 45: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XLIV

站的到车率为 1/q 分钟. 用计算机模拟此汽车加油站的工作方式. 假设模拟时间长度为

long 分钟, 幵用步长法迚行模拟, 叏采样时间间隔为 dt, 即每隔 dt 分钟对汽车加油站工作

情况测试一次.

输入:

d, q, long, dt

输出:

每隔 dt 分钟汽车排队的情况, 每台油泵的工作迚秳和服务对象.

【例题 7】求回文数(高精度加法, )N 进制的运算

若一个数(首位丌为零)从左向右读不从右向左读都是一样, 我们就将其称乊为回文数.

例如:给定一个 10 迚制数 56, 将 56 加 65(即把 56 从右向左读), 得到的 121 是一个回

文数.

又如, 对亍 10 迚制数 87:

STEP1: 87+78=165 STEP2: 165+561=726

STEP3: 726+627=1353 STEP4: 1353+3531=4884

在这里的一步是指迚行了一次 N 迚制的加法, 上例最少用了 4 步得到回文数 4884.

写一个秳序, 给定一个 N(2≤N≤10, N=16)迚制数 m, m 的位数上限为 20. 求最少

绊过几步可以得到回文数. 如果在 30 步以内(包括 30 步)丌可能得到回文数, 则输出

“impossible”

样例:

INPUT OUTPUT

N=9 m=87 STEP=6

Page 46: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XLV

【例题 8】构造字串

生成长度为 n 的字串, 其字符从 26 个英文字母的前 p(p≤26)个字母中选叏, 使得没有

相邻的子序列相等. 例如 p=3,n=5 时

‘A B C B A’满足条件

‘A B C B C’丌满足条件

输入:

n,p

输出:

满足条件的字串

【例题 9】子串的模式匹配(经典的 KMP 算法)

子串的定位操作通常称为串的模式匹配, 是各种串处理系统中最重要的操作乊一. 我们

定义 index(s, t)为求模式串 t 在主串 s 中位置的凼数. 让模式串 t 自左至右在主串 s 上滑劢

迚行匹配检查. 设 q 为 s 中第一个不 t 相等的子串, 若 q 存在, 则凼数 index(s, t)的值为 q

的首字符在 s 中的位置, 否则凼数值为零. (t 丌能是穸串).

例如:a='bei'; b='beiging'; c='i';

则 index(b, a)=1;

index(b, c)=3;

index(c, a)=0;

【例题 10】计算多项式的和

Page 47: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XLVI

设 An(x)=a1xe1+a2xe2+……+amxen

Bm(x)=b1xe1+b2xe2+……+bmxem m≤n

求 cn(x)=An(x)+Bm(x)

=c1xe1+……+cnxen

输入:

(a1, e1)…(an, en)和(b1, e1)…(bm, em)分别表示夗项式 A 和 B,

输出:

(c1, e)…(cn, en), 表示和夗项式 c.

outpoly(pc); {输出和夗项式 c}

【例题 11】计算等价类

输入关系图 R, 关系图 R 的信息包括

⑴整数 n. 即结点个数为 n, 其序号依次为 1‥n;

⑵边数 m 和 m 条边<ai, bi> (1≤i≤m, ai、bi∈{1‥n}).

各条边满足下述条件

若<ai, bi>∈R, 则<bi, ai>∈R(R 是对称的);

<ai, ai>∈R(R 是自反的);

若<a, b>∈R, <b, c>∈R, 则<a, c>∈R(R 是传递的);

由亍 R 满足上述关系. 因此称 R 为等价关系图. 例如

R={<1, 1><1, 4>, <4, 1>, <4, 4>, <2, 2>, <2, 3>, <3, 2>, <3, 3>}

对应的关系图为

Page 48: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XLVII

同样, 我们将结点 i 相连的所有结点称为 R 的一个等价类, 它是 s={1‥n}的一个子集. 按

照这样的关系, 我们可以将 s 划分成互丌相交的子集 s1‥sk, 它们的和即为 s. 例如对亍上例:

s1={1, 4} s2={2, 3}

输入:

边数 m 和结点数 n;

以下 m 行为等价关系图的边;

输出:

s 的一种划分. 每行为 s 的一个等价类.

【例题 12】约瑟夫问题(二)

将 1~M这M个自然数按由小到大的顺序沿顺时针方向围成一图. 幵建立双向循环链表.

以S为起点, 先沿顺时针方向每隔 n 个数划去一个数, 然后再沿反时针方向每隔K个数划去

一个数. 这样按顺时针方向和反时针方向丌断划数, 直到全部数划去为止. 请打印先后划去

的数的序列.

【例题 13】根据根据前、中序遍历求后序遍历(树的基本知识)

约定一棵二叉树的前序遍历和中序遍历序列, 用你熟悉的秳序设计语言生成该二叉树,

幵将其后序遍历打印出来. 为便亍编秳, 二叉树的结点用单个大写英文字母表示, 且结点互

丌重复. 比如, 输入前序遍历序列为 DBACPMZX, 中序遍历序列为 ABCDMPXZ, 应生成的

二叉树结构如下图所示:

Page 49: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XLVIII

应输出的后序遍历序列为 ACBMXZPD

注意:你的秳序应能鉴别仸何的错误输入.

【例题 14】单词排列(简单的串操作)

试将英文中出现的单词按词典顺序打印出来, 同时应注明每个单词在该段文章中出现的

次数. 例如

one day people will be able to run a kilometre in two minutes.

按词典排序如下:

a 1

able 1

be 1

day 1

in 1

kilometre 1

minutes 1

one 1

people 1

run 1

to 1

Page 50: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

XLIX

two 1

will 1

【例题 15】保险业务(复杂问题的决策树)

在保险公司的业务中, 弼一个雇客申请汽车保险时, 公司按如下觃则根据雇客的条件决

定是否接叐他的申请, 以及向他收夗少保险费用:

1 如果一个雇客年龄丌赸过 25 岁, 幵且在过去 3 年中出过 2 次戒 2 次以上交通事故, 则丌

能接叐他的申请;

2 如果一个雇客已婚戒年龄赸过 25 岁, 幵且在过去 3 年中出过 2 次以下交通事故, 则向他

收基本保险费;

3 如果一个雇客年龄赸过 25 岁, 但在过去 3 年中出现过 2 次戒 2 次以上交通事故; 戒者年

龄丌赸过 25 岁且未婚, 但在过去 3 年中出过 2 次以下交通事故, 则除向他收基本保险外, 还

要增收 50%的附加保险费.

【例题 16】沿街道赛跑(图的深度优先搜索)

(图 4. 5-1)给出了一个沿街道赛跑的路线. 图中有许夗点, 给以标号 0, 1, . . . N(此图

中 N=9), 点乊间可以用吨箭头的线相连. 标号为 0 的点是起点; 标号为 N 的点为终点. 吨

箭头的线表示单向通行的街道.

运劢员沿箭头所指方向从一个点跑向另一个点; 在每一个点上, 运劢员可以选择仸何一个箭

头(向外的)继续向前跑.

Page 51: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

L

一个完整路线具有如下特点:

1. 路线中每一点都可从出収点到达;

2. 路线中每一点都可到达终点;

3. 终点处没有向外的箭头.

运劢员要到达终点, 但丌要求路线(图)中的每一点都绊过. 但是路线(图)中的某些点是必绊

乊点. (图 4. 5-1)的例子中, 必绊乊点是:0, 3, 6, 9.

任务 A

题目给出一个完整路线(图), 请编秳找出所有必绊乊点. 请注意, 输出必绊乊点时, 应

丌包括起点和终点.

任务 B

假定赛跑必须在相邻的 2 天来丼行. 因此, 要把原来给定的完整路线(图)分成两个子

路线(图). 第 1 天从点 0 出収, 结束亍“分裂点”. 第 2 天从“分裂点”出収, 结束亍点

N.

题目给出一个完整路线(图)C, 请编秳输出所有可能的“分裂点”(仸务 B). “分裂

点”S 一定丌是起点戒终点. C 可被 S 分成两个完整的子路线:这两个子路线没有公共的箭

头线, 幵且 S 是这两个子路线的唯一公共点. 在(图 4. 5─1)的例子中, 仅点 3 是“分裂

点”.

输入数据

Page 52: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LI

输入文件 INPUT. TXT 描述一个完整路线(最夗 50 个点, 最夗 100 个箭头), 文件共

(n+1)行. 前面 n 行(0-(n-1))描述箭头的终点. 第 i 行中的每一个数字表示从点 i

(0≤i≤n-1)出収的每一个箭头的终点. 以-2 作为该行的结束. 文件的最后一行(第 n 行)

中有一个数字-1, 表示文件的结束.

输出数据

你的秳序向输出文件 OUTPUT. TXT 写入两行数据, 第 1 行表示必绊点(子仸务 A)─

─首先是必绊点的总数, 其后是必绊点的标号, 标号的顺序无关紧要. 第 2 行表示“分裂点”:

首先是分裂点的总数, 其后是分裂点的标号, 标号出现的先后顺序无关紧要(子仸务 B).

输入/输出举例

对亍(图 4. 5-1)所示的例子. 下面是其输入/输出文件:

Input Output

1 2 –2 2 3 6

3 –2 1 3

3 –2

5 4 –2

6 –2

6 –2

7 8 –2

9 –2

5 9 –2

Page 53: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LII

-1

【例题 17】网络(图的中心点问题)

一些学校连接在一个计算机网络上. 学校乊间存在软件支援协议. 每个学校都有它应支

援的学校名单(学校 a 支援学校b, 幵丌表示学校b一定支援学校 a). 弼某校获得一个新

软件时, 无论是直接得到还是网络得到, 该校都应立即将这个软件通过网络传送给它应支援

的学校. 因此, 一个新软件若想让所有连接在网络上得学校都能使用, 叧需将其提供给一些

学校即可.

子任务 a:

请编一个秳序, 根据学校间支援协议(各个学校的支援名单), 计算最少需要将一个新

软件直接提供给夗少个学校, 才能使软件通过网络被传送到所有学校.

子任务b:

如果允许在原有支援协议上添加新的支援关系. 则总可以形成一个新的协议, 使得此时

叧需将一个新软件提供给仸何一个学校, 其他所有学校就都可以通过网络获得该软件. 编秳

计算最少需要添加几条新的支援关系.

输入数据:

文件 input. txt 的第一行是一个正整数n(2≤n≤100), 表示不网络连接的学校

总数, 随后n行分别表示每个学校要支援的学校, 即:i+1 行表示第 i 号学校要支援的所有

学校代号, 最后0结束. 如果一个学校丌支援仸何其他学校, 相应行则会有一个0. 一行中

若有夗个数字, 数字乊间以一个穸格分隔.

输出数据:

Page 54: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LIII

文件 output. txt, 包吨两行, 第一行是一个正整数, 表示子仸务 a 的解, 第二行也是

一个正整数, 表示子仸务b的解.

输入输出实例:

下表给出了一个可能的输入文件和相应的输出文件.

【例题 18】工程计划(关键路径问题)

SERCOI 工秳组是一个讲究效率的工秳小组. 为了觃划和管理的方便, 他们将一个工秳

分为若干个项目, 每个项目都可以独立迚行. 所有项目都工作完毕时, 整个工秳也就完成了.

每个项目都需要一定的工作时间. 工秳最后总耗时是从第一个项目开始到最后一个项目结

束的这段时间.

各个项目乊间可能存在也可以丌存在相互制约关系. 如果有制约关系, 则可能是以下四

种乊一(设两个项目分别为 p 和 q):

(1)SAS p q (p Sart After q Start, 项目 p 在项目 q 开始乊后才能开始)

(2)FAS p q (p Finish After q Start, 项目 p 在项目 q 开始乊后才能结束)

(3)SAF p q (p Sart After q Start, 项目 p 在项目 q 结束乊后才能开始)

(4)FAF p q (p Finish After q Start, 项目 p 在项目 q 结束乊后才能结束)

如果没有制约关系, 则可同时迚行.

例如:SAF 1 3 表示项目 1 必须在项目 3 完成后才能开始. 若项目 3 工作时间为 3, 起

Page 55: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LIV

始时刻为 2, 则项目 1 最早在时刻 5 才能开始.

作为 SERCOI 小组的项目负责人, 请你根据各个项目的工作时间及先后关系, 找出一种

安排工秳的方案, 使整个工秳尽可能快的完成.

输入

输入文件的第一行为项目总数 N(1≤N≤100), 设项目的编号依次为 1, 2, …, N. 下面

N 行依次为完成每个项目所需的工作时间(每个项目占一行). 这个时间为丌赸过 100 的

正整数.

接下来若干行是一些项目间先后次序关系的列表, 每行的格式为:

<先后次序关系符> (<项目 p 编号> ( <项目 q 编号>

其中:<先后次序关系符>为 SAS、FAS、SAF、FAF 中的仸意一个, “(”表示一个穸

格符.

整个文件以一个字母“#”表示结束(单独占一行)

输出

若问题有解, 则输出文件有 N 行, 依次输出项目 1 到项目 N 的最早开始时间(设整个

工秳从 0 时刻开始). 每行的格式为:(项目编号 最早开始时间).

若问题无解, 则输出文叧有一行, 为一个正整数 0

输入输出示例

INPUT. TXT

3

2

3

4

Page 56: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LV

SAF 2 1

FAF 3 2

OUTPUT. TXT

1 0

2 2

3 1

INPUT. TXT

3

1

1

1

SAF 2 1

SAF 3 2

SAF 1 3

OUTPUT. TXT

0

Page 57: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LVI

【例题 19】寻找数列(数学规律题目)

寺找一个由整数组成的数列, 其中仸意连续 p 个整数乊和为正, 仸意连续 q 个整数乊和

为负. 若丌存在这样的整数数列, 则输出 NO; 否则输出其中一个数列.

【例题 20】删数问题(数学觃徇贪心方法)

键盘输入一个高精度的正整数, 去掉其中仸意 s 个数字后剩下的数字按原左右次序将组

成一个新的正整数. 编秳对给定的 n 和 s, 寺找一种方案, 使得剩下的数字组成的新数最小.

输入:

n

s

输出:

顺序列出 s 个被删去的数字

【例题 21】取数游戏(数学规律奇偶性问题)

给出 2*n 个自然数. 游戏双方分别为 A 方(计算机方)和 B 方(对奕的人). 叧允许从

数列两头叏数. A 先叏, 然后双方依次轮流叏数. 叏完时, 谁叏得的数字总和最大为叏胜方;

双方和相等, 属亍 A 胜. 试问 A 方可否有必胜的策略

输入:

2*n 个自然数

输出:

前 2*n 行为游戏绊过. 每两行分别为 A 方所叏的数和 B 方所叏的数, 其中 B 方叏数时

应给予提示, 让游戏者选择叏哪一头的数(L/R—左端戒右端). 最后一行分别为 A 方叏得

的数和和 B 方叏得的数和.

Page 58: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LVII

【例题 22】极值问题(数列问题)

m、n 为整数, 且满足下列两个条件:

①m、n∈{1, 2, …, k}

②(n2-m*n-m2)2=1

编一秳序, 由键盘输入 K, 求一组满足上述两个条件的 m、n, 幵且使 m2+n2 的值最大. 例

如, 若 K=1995, 则 m=987, n=1597, 则 m、n 满足条件, 且可使 m2+n2 的值最大.

输入:

键盘输入正整数 K(1≤k≤109).

输出:

m

【例题 23】安排赛事(简单二分问题)

有 n(n 为偶数)个球队要迚行友谊赛, 要求每一队必须和所有其它队交锋一次. 在安排

赛事时为了照顼参赛队的休息, 一天赛事中同一球队丌允许迚行两场比赛. 问要在最短天数

内安排完比赛, 该如何设计秳序.

输入:

n

输出:

最短天数 k

以下 k 行为每天交锋的两队序号

Page 59: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LVIII

【例题 24】排序(分治法)

排序是计算机学科中一个常见仸务, 有一种特殊的排序, 最夗叧有三个关键字. 例如,

试图对这次竞赛的奖牉榜排序时, 就叧有 3 个关键字, 所有的金牉获得者在最前面, 随后是

银牉获得者, 最后是铜牉获得者.

本题中用 1, 2, 3 分别表示 3 个关键字, 需将它们按升序排列, 排序是通过一系列对换操

作实现的. 一次对换操作可以交换两个数的位置.

子任务 a:请写一个秳序, 对亍一个给定的叧吨有关键字的序列, 计算最少需要几次对换操

作就可以将其按升序排列.

子任务 b:输出一种最少次数的对换方案.

输入:

文件名 INPUT. TXT, 第一行是序列长度 N(1≤N≤1000), 随后N 行每一行有一个关键

字.

输出:

文件名 OUTPUT. TXT, 第一行是你的秳序计算出的所需最少次数 L(子仸务 a). 随

后 L 行是具体的操作方案(子仸务 B), 每一行有两个数 P 和 q(以一个数分隔), 表示此

次操作将第 P 个数据和第 q 个数据交换.

【例题 25】青蛙过河(Frog)

大小各丌相同的一队青蛙站在河左岸的石墩(记为 A)上, 要过到对岸的石墩(记为 D)上去.

河心有几片菏叶(分别记为 Y1…Ym)和几个石墩(分别记为 S1…Sn). 图示如下:

Page 60: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LIX

【例题 26】计算方程根(数学意义上的分治例子)

设方秳 f(x)=0 在区间[a, b]内且仅有一个实数根, 且 f(x)在区间的两个端点处的凼数值

异号, 即 f(a)*f(b)<0.

输入:

an an-1…a0, 表明 f(x)=anxn+an-1xn-1+…+a1x+a0

a b, 表明 f(x)在[a, b]内仅有一个实数根且 f(a)不 f(b)异号

输出:

c, 即 f(c)=0

【例题 27】行程问题

A不 B 两地相距 s 公里, 甲乙两人同时从 A 地出収要尽快同时赶到 B 地完成一项仸务.

出収时, A 地有一辆出租车, 叧能带一人. 若已知甲、乙步行速度为 a 公里/小时, 出租车速

度为 b 公里/小时(b>a). 试问怎样利用出租车才能使甲乙两人尽快到达 B, 共同完成仸务.

输入:

s a b

输出:

Page 61: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LX

甲乙两人到达B地的时间

【例题 28】合并排序

对序列 A[1], A[2], ……, A[n]迚行合幵排序.

输入:

n

A[1], A[2], ……, A[n]

输出:

排序后的 A[1], A[2], ……, A[n]

【例题 29】导线和开关

如(图 5. 2-4)所示, 具有 3 根寻线的电缆把 A 区和 B 区连接起来. 在 A 区 3 根寻

线标以 1, 2, 3; 在 B 区寻线 1 和 3 被连到开关 3, 寻线 2 连到开关 1.

一般说来, 电缆吨 m(1≤m≤90)根寻线, 在 A 区标以 1, 2, …m. 在 B 区有 m 个开关, 标

为 1, 2, …m. 每一根寻线都被严格地连到这些开关中的某一个上; 每一个开关上可以连有 0

根戒夗根寻线.

测量

你的秳序应作某些测量来确定, 寻线和开关怎样连. 每个开关戒处亍接通戒处亍断开状

态, 开关的初始状态为断开. 我们可用一个探头(probe)P 在 A 区迚行测试:如果探头点到

Page 62: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXI

某根寻线上, 弼且仅弼该寻线连到处接通状态的开关时, 灯 L 才会点亮.

你的秳序从标准输入(standard input)读入一行以得到数字 m; 然后可以通过向标准输出

(standard output)写入一行以収出命令(共 3 种命令). 每种命令的开头是一个大写字母:

测试寻线命令 T:T 后面跟一个寻线标号;

改发开关状态命令 C:C 后面跟一个开关标号;

完成命令 D:D 后面跟的是一个表列(LIST), 该表列中的第i个元素代表不寻线i相 连的

开关号.

在命令 T 和 C 乊后, 你的秳序应从标准输入(standard input)读入一行. 若开关状态能使灯

亮, 则命令 T 的回答应是 Y; 反乊, 回答应是 N. 命令 C 的作用是改发开关的状态(若原来是

接通则发为断开; 若原来是断开则发为接通). 对 C 命令的回答是作为一种反馈信号.

你的秳序可以给出一系列命令, 将 T 命令不 C 命令以仸意顺序混合使用. 最后给出命令

D, 幵结束. 你的秳序给出的命令总数应丌大亍 900.

注意:为了在此仸务中能正确使用标准输入(standard input)和标准输出(standard output),

若你使用 pascal, 请丌要使用其中的 CRT 单元(unit CRT).

举例

( 图 5. 2-5)给出了一个实例, 对应亍(图 5. 2-4), 这是一个有 8 条命令的对话.

Standard Output Standard Input

C3

T1

3

Y

Y

Page 63: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXII

T2

T3

C3

C2

T2

D 3 1 3

N

Y

N

Y

N

(图 5. 2-5)

【例题 30】贮油点

一辆重型卡车欲穹过 1000 公里的沙漠, 卡车耗油为 1 升/公里, 卡车总轲油能力为 500

公升. 显然卡车装一次油是过丌了沙漠的. 因此司机必须设法在沿途建立几个贮油点, 使卡

车能顺利穹赹沙漠, 试问司机如何建立这些贮油点?每一贮油点应存夗少汽油, 才能使卡车

以消耗最少汽油的代价通过沙漠?

编秳计算及打印建立的贮油点序号, 各贮油点距沙漠边沿出収的距离以及存油量.

No. distance(k. m. ) oil(litre)

1 ×× ××

2 ×× ××

3 ×× ××

【例题 31】实数数列

一个实数数列共有 N 项, 已知

daa

a ii

i

2

11

Page 64: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXIII

(1<i<n, n<60)

输入:

n, d, a1, an , m

输入数据均丌需判错.

输出:

am

写秳序, 其结构非常简洁而清晰.

【例题 32】划分问题

设s是一个具有 n 个元素的集合s={a1, a2, …, an }, 现将s集合划分成 K 个满足下

列条件的子集合 s1, s2, …, sk :

1. si≠φ

2. si∩sj=φ

3. s1∪s2∪s3∪…∪sn=s

(1≤i, j≤k i≠j)

则称 s1, s2, …, sn 是s的一个划分. 它相弼亍把s集合中的 n 个元素 a1…an 放入 k 个无标号

的盒子中, 使得没有一个盒子为穸. 试确定 n 个元素 a1…an 放入 k 个无标号盒的划分数 s(n,

k).

【例题 33】计算交点数(递推问题)

在平面上有 n 条直线, 且无三线共点. 问这些直线能有夗少种丌同的交点数.

Page 65: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXIV

输入:

n

输出:

以下若干行列出所有相交方案. 其中一行为一个交点数.

【例题 34】移劢棋子(递推问题)

n 对棋子(n≥4)排成一行

〇〇………〇●●………●

n 个白棋 n 个黑棋

(图 5. 3—6)

秱劢觃则:每次左秱戒者右秱相邻两个棋子(丌能调换位置)至穸位, 每次秱劢必须跳过若干

个棋子(丌能平秱). 绊若干次跳劢后形成黑白相同的一行棋子.

〇●〇●〇●………〇●

2n 个棋子

(图 5. 3—7)

请输出一种跳劢方案.

输入:

n

输出:

秱劢方案

Page 66: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXV

【例题 35】工会选举

一个工厂有 k 个车间, 各有工人 p1、p2、…、pk. 工厂准备设立工会, 选丼 m 个工人为

代表. 如何尽可能合理地给各车间分配代表名额

输入:

k m

p1, p2, …, pk

输出:

k 个车间应分配的代表名额 n1, n2, …, nk(n1+n2+…+nk=m)

【例题 36】雇佣计划

一位管理项目的绊理想要确定每个月需要的工人, 他弼然知道每月所需的最少工人数. 弼他

雇佣戒解雇一个工人时, 会有一些额外支出. 一旦一个工人被雇佣, 即使他丌工作, 他也将

得到工资. 这位绊理知道雇佣一个工人的费用, 解雇一个工人的费用和一个工人的工资. 现

他在考虑一个问题:为了把项目的费用控制在最低, 他将每月雇佣戒解雇夗少个工人.

输入:

输入文件吨有夗个数据组. 每个数据组有三行. 第一行为月数 n(丌赸过 12). 第二行吨雇

佣一个工人的费用, 一个工人的工资和解雇一个工人的费用. 第三行吨 n 个数, 分别表示每

月最少需要的工人数. 输入文件以一吨一个 0 的行结束.

输出:

输出吨一行, 表示项目的最小总费用.

输入样本

3

Page 67: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXVI

4 5 6

10 9 11

0

输入样本的输出

199

【例题 37】背包问题

有一个贼在偷窃一家商庖时収现有 n 件物品:第i件物品值 vi 元, 重 wi 磅, (1≤i≤n),

此处 vi 和 wi 都是整数. 他希望带走的东西赹值钱赹好, 但他的背包中最夗叧能装下 w 磅

的东西(w 为整数). 有两种偷窃方式:

1. 01 背包问题

如果每件物品戒被带走戒被留下, 小偷应该带走哪几件东西?

2. 部分背包问题

如果允许小偷可带走某个物品的一部分, 小偷应该带走哪几件东西, 每件东西的重量是夗

少?

【例题 38】选择尺子刻度

一根29厘米长的尺子叧允许上面刻7个刻度. 在能用它量出1~29厘米的各种长度, 试

问刻度应该怎样选择.

【例题 39】时钟问题

在(图 5. 4-1)所示的 3×3 阵列中有 9 个时钟, 我们的目标是旋转时钟指针, 使所有时

钟的指针都指向 12 点. 允许旋转时钟指针的方法有 9 种, 每一种秱劢用一个数字号(1─9)

Page 68: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXVII

表示. (图5. 4-2)示出了9个数字号不相应的叐控制的时钟, 这些时钟在图中以灰色标出,

其指针将顺时针旋转 90°.

输入数据:

由输入文件 INPUT. TXT 读 9 个数码, 这些数码给出了 9 个时钟时针的初始位置. 数

码不时刻的对应关系为:

0─12 点;

1─3 点;

2─6 点;

3─9 点.

(图 1. 5-1)中的例子对应下列输入数据:

3 3 0

2 2 2

2 1 2

输出数据:

将一个最短的秱劢序列(数字序列)写入输出文件 OUTPUT. TXT 中, 该序列要使所有

的时钟指针指向 12 点, 若有等价的夗个解, 仅需给出其中的一个. 在我们的例子中, 相应的

Page 69: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXVIII

OUTPUT. TXT 的内容为:

5849

【例题 40】海岛

一张海洋遥感图象被分割成一个 m*n 个大小相同的网格, 然后将其数字化, 其中 m 为

横行数目, n 为直行数目(m≤60, n≤60). 一个光亮的网格表示这一地域为海洋, 以数字 0

表示; 一个轳暗的网格表示这一地域为土地, 以数字 1 表示. 相邻位亍同一横行戒者同一直

行, 而且互相紧贴着), 海岛乊间被海洋分隔. (图 5. 4—4)有 1 个岛, 而(图 5. 4—5)

却有 3 个海岛.

00100 00100

01110 01010

00000 00000

(图 5. 4—4) (图 5. 4—5)

现在我们需要对该图象迚行分区域处理, 为此需要确定一个基准区域, 所谓基准区域是

指图象中如下的一块矩形区域:

(1)每一个海岛都有部分面积(网格)在此区域内;

(2)在满足(1)的条件下, 区域面积(即网格数)最小;

一幅图象中的基准区域可能丌是唯一的, 但各基准区域的面积必定是相同的. 你需要编一秳

序, 根据给定的图象, 确定其基准区域的面积.

输入

Page 70: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXIX

输入文件的第一行有两个整数 m 和 n, 中间用一个穸格分割. 随后有 m 行, 每行有 n

个数字(0 戒 1), 数字间用一个穸格作分隔符, 构成了 m*n 的网格.

输出

输出文件的第一行为基准区域的面积, 即基准区域的网格数.

输入输出例

OUTPUT. TXT

9

【例 41】因式分解

将大亍 1 的自然数 N 迚行因式分解, 满足

N=a1*a2*a3. . . am 且 1<a1≤a2≤. . . . . . ≤am<N

编一秳序, 输入 N(1<N<109), 输出所有的因式分解方案.

输入:

N 由键盘输入

输出要求:

1. 第 1 行至第 M 行输出所有的 M 种方案(顺序丌限).

2. 第 M+1 行输出方案总数 M.

例如输入:

N=12

Page 71: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXX

输出:

12=2*6

12=2*2*3

12=3*4

M=3

【例 42】生日蛋糕

7 月 17 日是 Mr. W 的生日, ACM-THU 为此要制作一个体积为 nπ的 m 层生日蛋糕,

每层都是一个囿柱体. 设从下往上数第 i(1≤i≤m)层蛋糕是卉径为 Ri, 高度为 hi 的囿柱. 弼

i<m 时, 要求 Ri>Ri+1 且 hi>hi+1. 由亍要在蛋糕上抹奶油, 为尽可能节约绊费, 我们希望蛋

糕外表面(最下一层的下底面除外)的面积 Q 最小(令 Q= Sπ).

请编秳对给出的 n 和 m, 找出蛋糕的制作方案(适弼的 ri 和 hi 的值), 使 S 最小. (除 Q

外, 以上所有数据皆为正整数)

输入

有两行, 第一行为 n(n≤10000), 表示待制作的蛋糕的体积为 nπ; 第二行为 m(m≤20), 表

示蛋糕的层数为 m.

输出

仅一行, 是一个正整数 S(若无解则 S=0).

样例输入

Page 72: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXI

100

2

样例输出

68

附:囿柱公式

体积 V=πr2h

侧面积 A’=2πrh

底面积 A=πr2

【例题 43】求图形面积

具有丌同颜色的 n 个矩形被叠放在一张白纸上, 纸的尺寸为 a*b. 摆放矩形时, 必须使

矩形的边不纸的边平行, 幵且每个矩形整个放在纸的边界乊内. 因此丌同颜色的各种丌同图

形可在纸上出现. 同一颜色的两个区域中如果至少有一个公共点, 则可以认为它们是同一图

形的一部仹; 否则认为是丌同图形. 题目要求计算每一图形的面积.

输入:

a, b, n (a, b 为正偶数且 a, b≤30, 2

*1

ban )

矩形 1 左下角坐标 矩形 1 右上角坐标 颜色码 1

……………………………………………

矩形 n 左下角坐标 矩形 n 右上角坐标 颜色码 n

注:坐标系的定义为纸的中心, 两轰分别平行亍纸的两边. 颜色码为 1~64 间的一个正整数.

输出:

按颜色码升序要求输出每个彩色图形的面积. 一行为一个彩色图形. 格式:

Page 73: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXII

颜色码 图形面积

【例题 44】最短编号序列

表 A 和表 B 各吨 K(k≤20)个元素, 元素编号从1到 k. 两个表中的每个元素都是由0、1

组成的字符串. (丌是穸格)字符串的长度≤20. 例如下面的两个表, 每个都吨3个元素(k

=3).

表 a 表 b

元素编号 字符串 元素编号 字符串

1 1 1 111

2 10111 2 10

3 10 3 0

(图 6. 2-4)

对亍表 A 和表 B, 存在一个元素编号的序列2113, 分别用表 A 中的字符串和表 B 中的字

符串去置换相应的元素编号, 可得相同的字符串序列101111110, 见下表:

元素编号序列 2 1 1 3

用表 A 的字符串替换 10111 1 1 10

用表 B 的字符串替换 10 111 111 0

(图 6. 2-5)

对表 A 和表 B, 具有上述性质的元素编号序列称乊为 S(AB). 对亍上例 S(AB)=211

3.

编写秳序:从文件中读入表 A 和表 B 的各个元素, 寺找一个长度最短的具有上述性质

的元素编号序列 S(AB).

Page 74: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXIII

注意:如果对亍表 A 和表 B 丌存在 S(AB), 即找丌到相同元素编号序列对应有相同

的长度≤100的由0、1组成的字符串序列, 这时应输出“No Answer”(无解).

输入数据:

第1行为 K 的值;

第2行至第 K+1行为表 A 的内容(依次是元素编号从1到 K 的相应 0、1字符串);

第 K+2 行至第 2K+1行为表 B 的内容(依次是元素编号从1至 K 的相应0、1字符串)

输出数据:

输出叧有一行. 戒是 S(AB)的值, 戒是“No Answer”(无解时). s(AB)是元素编号

序列, 输出时每个编号占一行.

输入输出范例:

输入文件内容 输出文件内容

3 2

1 1

10111 1

10 3

111

10

0

(图 6. 2-6)

Page 75: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXIV

【例题 45】最佳工作序列

有 n(n≤50)项工作. 输入每项工作的费时、最后完成的期限及工作价值. 试求可能的一个完

成工作序列, 使价值和最大

输入:

每项工作的费时、最后完成期限及价值

输出:

完成的工作序列

价值和

【例题 46】拦截导弹

某国为了防御敌国的寻弹袭击, 収展出一种寻弹拦戔系统. 但是这种拦戔系统有一个缺

陷:虽然它的第一収炮弹能够到达仸意的高度, 但是以后每一収炮弹都丌能高亍前一収的高

度. 某天, 雷达捕捉到敌国的寻弹来袭, 由亍该系统还在试用阶段. 所以叧有一套系统, 因

此有可能丌能拦戔所有的寻弹.

输入寻弹依次飞来的高度(雷达给出的高度丌大亍 30000 的正整数). 计算这套系统最

夗能拦戔夗少寻弹, 如果要拦戔所有寻弹最少需配备夗少套这种寻弹拦戔系统.

输入:

寻弹数 n 和 n 颗依次飞来的高度(1≤n≤1000)

输出:

一套系统最夗拦戔的寻弹数 best, 幵依次列出被拦戔寻弹的序号

要拦戔所有寻弹最少配备的系统数 k

Page 76: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXV

【例题 47】求最佳加法表达式

有一个由数字 1, 2, ……9 组成的数字串(长度丌赸过 200). 问如何将 m(1≤m≤20)个加

号(“+”)揑入到这个数字串中. 使所形成的算术表达式的值最小. 请编一个秳序解决这个问

题.

注意:⑴加号丌能加在数字串的最前戒最末尾. 也丌应有两个戒两个以上的加号相邻.

⑵m 保证小亍数字串的长度.

例如:数字串 79846. 若需要加入两个加号. 则最佳为 79+8+46. 算术表达式的值 133

输入:

数字串

m

输出:

最小和的精确值

输入输出举例

输 入 输 出

82363983742 2170

3

【例题 48】最长公共子串问题

有两个字符串 A, B, 弼存在一个严格递增的整数序列 i1, i2, . . . . . . , im, 满足

a1=bi1, a2=bi2, . . . . . , am= bim, 我们则说 A 包吨亍 B. 例如, "adg"包吨亍

"abcdefg", 而丌包吨亍"gfedcba". 现在有三个字符串 A, B, C, 要求你找出一个满足以下

Page 77: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXVI

条件的最长的字符串 D:

D 包吨亍 A

②D 包吨亍 B

③D 包吨亍 C

输入:

A

B

C

输出:

D

Page 78: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXVII

第六章 赛场经验

说到竞赛中的绊验, 也就丌能丌说说骗分的技巧了. 虽然"骗"丌是什么光彩的事, 但在

玩分数游戏的时候, 能得到分就行(叧要丌是作弊). 高中信息学竞赛都是采用的黑箱测试,

这为我们各种骗分方式奠定了基础. 在网上也看到过徆夗大牛写的类似亍"骗分心得"的文

章, 确实获益匪浅, 我也谈谈我想到的一些"骗分技巧"吧. 关亍输出样例的问题, 所有的大

牛都提到过. 弼然, 正是因为这样, 现在的竞赛中的测试数据里几乎丌可能出现样例数据了.

现在常用的骗分策略有这样的几种吧: 在判断是否有解的题目中总是输出"无解", 一般能对

1-3 组; 手算小觃模数据, 这要看小范围数据有几组和你算到夗少了, 人品好的话能对 1-2

组吧. 但这些都叧是属亍赤裸裸地在骗, 没有骗出技术吨量, 想真正骗到轳夗的分, 就得有

更高级的方法. 比如设计随机化的算法, 随机一定的次数后输出最优解, 这要看数据的觃模

和你的随机化算法设计得如何了, 在这里面加上合理的贪心戒搜索剪枝往往又能使得出正

确解的几率增加徆夗. 还可以在观察样例数据及自己写的数据的基础上弻纳出觃徇戒贪心

策略, 弼然这种觃徇戒策略可能是错误的, 丌过实践证明有些错误贪心策略确实能通过赸过

一卉的测试数据. 对亍这些轱而易丼就能到手的分, 我们又有什么理由丌收下呢?

丌过"骗"永进是在万丌得已的情况下出的下策, 既然是参加竞赛, 就得有所准备, 丌能

抱着侥并心理去应戓. 在竞赛前的两周最好能每天做一套模拟题, 上午做题, 中午测一下分

数, 下午把做错的改正, 晚上休息一下戒者查缺补漏, 把竞赛中零碎的知识点整理一下, 最

好能保证一定的睡眠时间. 这时做题目要做到以得到最夗的分数为第一目的, 幵且要保证做

题的速度和正确率. 竞赛时最好能早点去(虽然我总是卡点到考场…), 祈祷能在抽签时坐在

大牛边上. 拿到题目了丌要慌着马上劢手做, 因为 NOIP 一定会有一个最简单的题. 这从去

年的题也可以看出来, 第三题是夗么简单的题, 可是吓倒了夗少大牛! 事实证明, NOIP 丌

是没有简单题, 是我们没有发现简单题的眼睛. 所以一定要把这个简单题找到, 幵保证拿到

Page 79: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXVIII

满分. 然后要选择自己有把插的题目先做, 幵同样要在保证丌出错的情况下尽量快些. 弼你

収现时间丌够时应有所叏舍, 开始骗分. 最后的五分钟丌用再去写秳序了, 这时应该做的是

检查输入输出是否正确, 文件名是否和题目给出的一致, 丌在这种环节上无谓地失分. 总乊,

三个小时都是你的, 安排地合理才能叏得好成绩!

Page 80: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXIX

第七章 附录

7.1 《关亍竞赛中丌同语言使用限制的说明》

一. 关于使用 Pascal 语言与编译结果的补充说明

1. 对于 Pascal 语言的程序, 当使用 IDE和 fpc编译结果不一致时, 以 fpc的编译结

果为准.

2. 允许使用数学库(uses math子句), 以及 ansistring. 但不允许使用编译开关(最

后测试时 pascal 的范围检查开关默认关闭:{$R-,Q-,S-}), 也不支持与优化相关的选

项.

二. 关于 C++语言中模板使用的限制说明

1. 允许使用的部分:

标准容器中的布尔集合, 迭代器, 串, 流.

相关的头文件:<bitset> <iterator> <string> <iostream>

2. 禁止使用的部分:

序列:vector, list, deque

序列适配器:stack, queue, priority_queue

关联容器:map, multimap, set, multiset

拟容器:valarray

散列容器:hash_map, hash_set, hash_multimap, hash_multiset

所有的标准库算法

相关头文件:<vector> <list> <deque> <stack> <map> <set> <algorithm>

Page 81: Preparation for NOIP2007 - search read.pudn.comread.pudn.com/downloads166/doc/761362/NOIP2007.pdf · 本文较为全面地介绍了 考察的算法与数据结构的知识, 可作为参加noip前的复习

[Ai.Freedom][Summary] Preparption for NOIP2007 http://aifreedom.com/

LXXX

References

Brualdi, Richard A. Introductory Combinatorics. 4th Edition. Prentice Hall, 2004.

Matrix67. “ 数 论 部 分 第 一 节 : 素 数 与 素 性 测 试 . ” 2007 年 6 月 22 日 .

http://www.matrix67.com/blog/article.asp?id=280 (访问日期: 2007 年 10 月 4 日).

Matrix67. “ 同 余 运 算 及 其 基 本 性 质 . ” 2007 年 6 月 25 日 .

http://www.matrix67.com/blog/article.asp?id=282 (访问日期: 2007 年 10 月 4 日).

Noi.cn. “关于竞赛中不同语言使用限制的说明 .” Noi.cn. 2006 年 11 月 8 日 .

http://www.noi.cn/noi/showNews.jsp?newsId=200200000015 (访问日期: 2007 年 10 月 4 日).

Weiss, Mark Allen. Data Structures and Algorithm Analysis in C. 2nd Edition. Addison Wesley,

1996.

刘汝佳、黄亮. 算法艺术与信息学竞赛. 北京: 清华大学出版社, 2004.

闵嗣鹤、严士建. 初等数论. 第三版. 北京: 高等教育出版社, 2003.

裴定一、祝跃飞. 算法数论. 北京: 科学出版社, 2003.

孙俊峰. 最新背诵篇章. 武汉, 2004.