NOIP2008提高组复赛试题及题解
- 格式:doc
- 大小:202.00 KB
- 文档页数:14
NOIP2008信息奥赛提高组试题与答案(Pascal语言)第14届信息学奥赛试题单项选择1. 在以下各项中,()不是操作系统软件。
A.Solaris B.Linux C.Sybase D.Windows Vista E.Symbian2. 微型计算机中,控制器的基本功能是()。
A. 控制机器的各个部件协调工作B.实现算数运算与逻辑运算C.存储各种控制信息D. 获取外部信息E.存放程序和数据3. 设字符串S=“Olympic”,S的非空字串的数目是()。
A.29B.28C.16D.17E.74. 完全2叉树有2*N-1的结点,则它的叶子结点数目是()。
A.N-1B.2*NC.ND.2^N-1E.N/25. 将数组{8,23,4,16,77,-5,53,100}中元素从大到小按顺序排序,每次可以交换任意两个元素,最少要交换()次。
A.4B.5C.6D.7E.86.设栈S的初始状态为空,元素a,b,c,d,e,f依次入栈,出栈顺序为b,d,c,f,e,a那么栈容量至少该是()A.6B.5C.4D.3E.27.与十进制数28.5625相等的四进制数是()A.123.21B.131.22C.130.22D.130.21E.130.208.递归过程和函数调用时,处理参数和返回地址,通常使用一种称为()的数据结构。
A.队列B.多维数组C.线性表D.链表E.栈9.TCP/IP 是一组构成互联网基础的网络协议,字面上包括两组协议:传输控制协议(TCP)和网际互联协议(IP)。
TCP/IP协议把Internet网络系统描述成具有4个层次功能的网络模型,其中提供源节点和目的节点之间的信息传输服务,包括寻址和路由器选择等功能的是()。
A.链路层B.网络层C.传输层D.应用层E.会话层10.对有序数组{5,13,19,21,37,56,64,75,88,92,100}进行二分查找,等概率情况下,查找成功的平均查找长度(平均比较次数)是()。
NOIP1995年复赛试题1. 设有下列的算式:求出□中的数字,并打印出完整的算式来。
8 0 9 ------------- □□) □□□□ □□------------- □□□ □□□ ------------- 12. 方阵填数:在一个N ⨯N 的方阵中,填入1,2,……N ⨯N 个数,并要求构成如下的格式: 例:3. 若将一个正整数化为二进制数,在此二进制数中,我们将数字1的个数多于数字0的个数的这类二进制数称为A 类数,否则就称其为B 类数。
例如:(13)10=(1101)2 其中1的个数为3,0的个数为1,则称此数为A 类数; (10)10=(1010)2 其中1的个数为2,0的个数也为2,称此数为B 类数; (24)10=(11000)2 其中1的个数为2,0的个数为3,则称此数为B 类数; 程序要求:求出1~1000之中(包括1与1000),全部A 、B 两类数的个数。
4.编码问题:设有一个数组A:ARRAY[0..N-1] OF INTEGER ;数组中存放的元素为0~N-1之间的整数,且A[i]≠A[j](当i ≠j 时)。
例如:N=6时,有: A=(4,3,0,5,1,2) 此时,数组A 的编码定义如下: A[0]的编码为0;A[i]的编码为:在A[0],A[1],……A[i-1]中比A[i]的值小的个数(i=1,2……N-1) ∴上面数组A 的编码为:B=(0,0,0,3,1,2)程序要求解决以下问题:给出数组A 后,求出其编码;给出数组A 的编码后,求出A 中的原数据。
5. 灯的排列问题:设在一排上有N 个格子(N ≤20),若在格子中放置有不同颜色的灯,每种灯的个数记为N 1,N 2,……N k (k 表示不同颜色灯的个数)。
放灯时要遵守下列规则:同一种颜色的灯不能分开;不同颜色的灯之间至少要有一个空位置。
例如:N=8(格子数) R=2(红灯数) B=3(蓝灯数) 放置的方法有:N=513 14 15 16 1 12 23 24 17 2 11 22 25 18 3 10 21 20 19 4 9 8 7 6 5N=616 17 18 19 20 1 153****221214 29 36 33 22 3 132****423412 27 26 25 24 5 11 10 9 8 7 6B-R 顺序放置的总数为12种。
全国青少年信息学奥林匹克联赛复赛模拟试题湖南省长沙市第一中学周祖松1.无限序列(infinit.pas/c/cpp)【问题描述】我们按以下方式产生序列:1、开始时序列是: "1" ;2、每一次变化把序列中的 "1" 变成 "10" ,"0" 变成 "1"。
经过无限次变化,我们得到序列"1011010110110101101..."。
总共有 Q 个询问,每次询问为:在区间A和B之间有多少个1。
任务写一个程序回答Q个询问输入第一行为一个整数Q,后面有Q行,每行两个数用空格隔开的整数a, b。
输出共Q行,每行一个回答约定∙ 1 <= Q <= 5000∙ 1 <= a <= b < 263样例分析:我们先看看序列变化规律,S1 = "1", S2 = "10", S3 = "101", S4 = "10110", S5 = "10110101", 等等. Si 是 S(i+1)的前缀。
序列Si 是由序列 S(i-1)和 S(i-2), 连接而成的。
即Si = Si-1 + Si-2 (实际上上是Fibonacci数列)。
找到规律以后,我们可以可以用递归的方法求出从从位置1到位置X之间所有的1的个数,用一个函数F计算,结果为f(b)-f(a-1)。
时间复杂度为: O(Q * log MAX_VAL)此题需要先找出数学规律,再进用递归实现。
主要考查选手的数学思维能力和递归程序的实现。
源程序:constnn=92; //进行92次的数列扩展后,数列长度就会超过给定的数据范围,varf,ft:array[0..nn] of int64;q,i,j,l1,l2:longint;a,b:qword;procedure prapre;{预处理}var i:longint;beginf[0]:=1;f[1]:=1;ft[0]:=0;ft[1]:=1;for i:=2 to nn dobeginf[i]:=f[i-1]+f[i-2];ft[i]:=ft[i-1]+ft[i-2];end;end;function find(a:int64;ll:longint):int64;{求这个数列的前a个有多少个1}beginif a=0 then exit(0);find:=0;if a=f[ll] then find:=ft[ll] elseif a<=f[ll-1] then find:=find(a,ll-1)else find:=ft[ll-1]+find(a-f[ll-1],ll-2);end;beginassign(input,'infinit.in');reset(input);assign(output,'infinit.out');rewrite(output);prapre;readln(q);for i:=1 to q dobeginreadln(a,b);writeln(find(b,nn)-find(a-1,nn));end;close(input);close(output);end.2.删数(remove.pas/c/cpp)【问题描述】有N个不同的正整数数x1, x2, ... x N排成一排,我们可以从左边或右边去掉连续的i个数(只能从两边删除数),1<=i<=n,剩下N-i个数,再把剩下的数按以上操作处理,直到所有的数都被删除为止。
【noip2008年提高组题二】火柴棒等式问题描述:在火柴棒等式中,每个数字由若干火柴棒组成,要求组成一个等式。
等式中有加号、等号和两个数字,它们之间各自由若干火柴棒连接起来。
若干数字的顺序和下标之和相等,则等式成立。
已知通过7根火柴棒可以得到的合法的等式有12个,求合法的所有等式。
解题思路:本题为全排列问题的一个典型应用。
根据题目给出的火柴棒等式的要求,遍历所有的7根火柴棒的全排列,验证是否能组成合法的火柴棒等式,并将符合条件的等式输出即可。
以下为详细步骤:1. 构建火柴棒数量列表,用于表示每个数字所需的火柴棒数量。
列表的下标表示数字,列表的值表示火柴棒数量;2. 生成7根火柴棒的全排列,并将每一个排列结果作为一个可能的等式;3. 遍历所有可能的等式,判断是否符合题目要求:等式中有加号、等号和两个数字,它们之间各自由若干火柴棒连接起来。
若干数字的顺序和下标之和相等,则等式成立;4. 将符合条件的等式输出。
以下为Python代码实现:def dfs(total, cur):if cur == 7:judge(total)returnfor i in range(10):if num[i] > 0:num[i] -= 1dfs(total + ch[cur][i], cur + 1)num[i] += 1def judge(total):for i in range(10):if num[i] != 0:returna, b, c = total[0], total[1], total[2]if a + b == c and a <= b:res.append(total)ch = [[6, 2, 5, 5, 4, 5, 6, 3, 7, 6] for _ in range(7)]num = [2, 5, 5, 4, 5, 6, 3, 7, 6, 6]res = []dfs([], 0)for i in range(len(res)):print(f'{res[i][0]} + {res[i][1]} = {res[i][2]}')在上述代码中,ch为火柴棒数量列表,num为每个数字所需的火柴棒数量。
全国信息学奥林匹克联赛(NOIP2008)复赛普及组注意事项:1、文件名(程序名和输入输出文件名)必须使用小写。
2、C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0。
3、全国统一评测时采用的机器配置为:CPU 1.9GHz,内存512M,上述时限以此配置为准。
各省在自测时可根据具体配置调整时限。
1.ISBN号码(isbn.pas/c/cpp)【问题描述】每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。
ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔之后的五位数字代表该书在出版社的编号;最后一位为识别码。
识别码的计算方法如下:首位数字乘以1加上次位数字乘以2......以此类推,用所得的结果mod 11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。
例如ISBN号码0-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2, (9)再求和,即0×1+6×2+……+2×9=158,然后取158 mod 11的结果4作为识别码。
你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出你认为是正确的ISBN号码。
【输入】输入文件isbn.in只有一行,是一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。
【输出】输出文件isbn.out共一行,假如输入的ISBN号码的识别码正确,那么输出“Right”,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符“-”)。
2008第十四届全国青少年信息学奥林匹克联赛初赛试题(提高组 C 语言二小时完成)●● 全部试题答案均要求写在答卷纸上,写在试卷纸上一律无效●●一、单项选择题(共10题,每题1.5分,共计15分。
每题有且仅有一个正确答案)。
1. 在以下各项中,()不是操作系统软件。
Symbian2.微型计算机中,控制器的基本功能是()。
A. 控制机器各个部件协调工作B. 实现算术运算和逻辑运算C. 存储各种控制信息D. 获取外部信息3. 设字符串S=”Olympic”,S的非空子串的数目是()。
A. 29B. 28C. 16D. 17E. 74.完全二叉树共有2*N-1个结点,则它的叶节点数是()。
A. N-1B. 2*NC. ND. 2N-1E. N/25.将数组{8, 23, 4, 16, 77, -5, 53, 100}中的元素按从大到小的顺序排列,每次可以交换任意两个元素,最少需要交换()次。
A. 4B. 5C. 6D. 7E. 86.设栈S的初始状态为空,元素a,b,c,d,e,f依次入栈S,出栈的序列为b,d,c,f,e,a,则栈S的容量至少应该是()。
A. 6B. 5C. 4D. 3E. 27. 与十进制数28.5625相等的四进制数是()。
A. 123.21B. 131.22C. 130.22D. 130.21E. 130.208.递归过程或函数调用时,处理参数和返回地址,通常使用一种称为()的数据结构。
A. 队列B. 多维数组C. 线性表D. 链表E. 栈1 A. Solaris B. Linux C. Sybase D. Windows Vista E. E. 存放程序和数据9. TCP/IP是一组构成互联网基础的网络协议,字面上包括两组协议:传输控制协议(TCP)和网际协议(IP)。
TCP/IP 协议把Internet网络系统描述成具有四个层次功能的网络模型,其中提供源节点和目的节点之间的信息传输服务,包括寻址和路由器选择等功能的是()。
【noip2008年提高组题二】火柴棒等式题目描述:给定一个由火柴棒拼成的数字等式,例如:"3-2+1=4",要求你判断这个等式是否成立。
输入格式:等式(由数字、加减乘除号组成)。
输出格式:如果等式成立,输出 "Yes",否则输出 "No"。
数据范围:等式长度为5-10,且只包含数字0-9,加号、减号、等号。
样例:输入:3-2+1=4输出:Yes解题思路:这道题可以使用模拟的方法进行求解。
首先,我们需要模拟火柴棒的移动过程,判断等式是否成立。
具体来说,我们可以从左到右遍历等式,依次判断每个字符代表的火柴棒是否能够移动到正确的位置。
如果能够移动到正确的位置,则说明等式成立;否则,说明等式不成立。
具体步骤如下:1. 初始化一个计数器变量count为0,用于记录当前位置的火柴棒数量。
2. 从左到右遍历等式中的每个字符:如果当前字符是数字,则将其转换为对应的火柴棒数量,并将其加到count中。
如果当前字符是加号或减号,则将其转换为对应的火柴棒数量,并将其加到count中。
同时,还需要判断下一个字符是否为数字,如果是数字,则将其转换为对应的火柴棒数量,并将其加到count中;如果不是数字,则说明等式不成立,直接返回"No"。
如果当前字符是等号,则判断count是否等于等号右边的火柴棒数量,如果相等则说明等式成立,返回"Yes";否则说明等式不成立,返回"No"。
3. 如果遍历完整个等式后仍然没有返回结果,则说明等式不成立,返回"No"。
代码实现:以下是Python语言的代码实现:```pythondef matchSticks(s: str) -> str:count = 0 计数器变量,记录当前位置的火柴棒数量for i in range(len(s)):if s[i].isdigit(): 当前字符是数字count += int(s[i]) 将数字转换为火柴棒数量并加到count中elif s[i] in ['+', '-']: 当前字符是加号或减号if i + 1 < len(s) and s[i + 1].isdigit(): 下一个字符是数字count += int(s[i + 1]) 将数字转换为火柴棒数量并加到count 中else: 下一个字符不是数字,说明等式不成立return "No"elif s[i] == '=': 当前字符是等号if count == int(s[i + 1]): 判断count是否等于等号右边的火柴棒数量return "Yes" 等式成立,返回"Yes"else: 等式不成立,返回"No"return "No"return "No" 如果遍历完整个等式后仍然没有返回结果,说明等式不成立,返回"No"```。
全国信息学奥林匹克分区联赛(NOIP)复赛提高组试题第一届全国信息学奥林匹克分区联赛(NOIP1995)复赛试题(提高组竞赛用时:3.5小时)1、编码问题设有一个数组A:ARRAY[0..N-1]OFINTEGER;数组中存放的元素为0~N-1之间的整数,且A[i]≠A[j](当i≠j时)。
例如:N=6时,有:A=(4,3,0,5,1,2)此时,数组A的编码定义如下:A[0]的编码为0;A[i]的编码为:在A[0],A[1],…,A[i-1]中比A[i]的值小的个数(i=1,2,…,N-1)∴上面数组A的编码为:B=(0,0,0,3,1,2)程序要求解决以下问题:①给出数组A后,求出其编码。
②给出数组A的编码后,求出A中的原数据。
2、灯的排列问题设在一排上有N个格子(N≤20),若在格子中放置有不同颜色的灯,每种灯的个数记为N1,N2,……N k(k表示不同颜色灯的个数)。
放灯时要遵守下列规则:①同一种颜色的灯不能分开;②不同颜色的灯之间至少要有一个空位置。
例如:N=8(格子数);R=2(红灯数);B=3(蓝灯数),放置的方法有:R-B顺序B-R顺序放置的方法总数为12种。
数据输入的方式为:NP1(颜色,为一个字母)N1(灯的数量)P2 N2……Q(结束标记,Q本身不是灯的颜色)程序要求:求出一种顺序的放置(排列)方案及放置(排列)方案总数。
3、积木块上的数字设有一个四层的积木块,1~4层积木块的数量依次为:5,6,7,8,如下图所示放置:其中,给出第三层与第四层所标示的数字,并已知第三层的数据是由第四层的数据计算出来的。
计算的方法是:第三层的某个数据A是由第四层相邻的两个数据B,C经过某种计算后产生的:计算所用到的计算符为:+,-,⨯,且无优先级之分(自左向右计算),运算符最多为2个。
如:3+4⨯5=35 5⨯4+3=23可以看出,上图中的第三层的数据是由第四层的数据用以下计算公式计算出来的:A=B⨯C+B也就是:8=2⨯3+2,15=3⨯4+3,……14=2⨯6+2程序要求:给出第四层与第三层的数据后,将第一、二层的每块积木标上相应的数据,并输出整个完整的积木图及计算公式。
第十届全国信息学奥林匹克分区联赛(NOIP2004)复赛试题(提高组竞赛用时:3小时)1、津津的储蓄计划(Save.pas/dpr/c/cpp)【问题描述】津津的零花钱一直都是自己管理。
每个月的月初妈妈给津津300元钱,津津会预算这个月的花销,并且总能做到实际花销和预算的相同。
为了让津津学习如何储蓄,妈妈提出,津津可以随时把整百的钱存在她那里,到了年末她会加上20%还给津津。
因此津津制定了一个储蓄计划:每个月的月初,在得到妈妈给的零花钱后,如果她预计到这个月的月末手中还会有多于100元或恰好100元,她就会把整百的钱存在妈妈那里,剩余的钱留在自己手中。
例如11月初津津手中还有83元,妈妈给了津津300元。
津津预计11月的花销是180元,那么她就会在妈妈那里存200元,自己留下183元。
到了11月月末,津津手中会剩下3元钱。
津津发现这个储蓄计划的主要风险是,存在妈妈那里的钱在年末之前不能取出。
有可能在某个月的月初,津津手中的钱加上这个月妈妈给的钱,不够这个月的原定预算。
如果出现这种情况,津津将不得不在这个月省吃俭用,压缩预算。
现在请你根据2004年1月到12月每个月津津的预算,判断会不会出现这种情况。
如果不会,计算到2004年年末,妈妈将津津平常存的钱加上20%还给津津之后,津津手中会有多少钱。
【输入文件】输入文件save.in包括12行数据,每行包含一个小于350的非负整数,分别表示1月到12月津津的预算。
【输出文件】输出文件save.out包括一行,这一行只包含一个整数。
如果储蓄计划实施过程中出现某个月钱不够用的情况,输出-X,X表示出现这种情况的第一个月;否则输出到2004年年末津津手中会有多少钱。
【样例输入1】29023028020030017034050908020060【样例输出1】-7【样例输入2】29023028020030017033050908020060【样例输出2】1580【问题描述】在一个果园里,多多已经将所有的果子打了下来,而且按果子的不同种类分成了不同的堆。
Day1铺地毯【问题描述】为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯。
一共有n 张地毯,编号从1 到n。
现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上。
地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号。
注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖。
【输入】输入文件名为 carpet.in。
输入共 n+2 行。
第一行,一个整数 n,表示总共有n 张地毯。
接下来的 n 行中,第i+1 行表示编号i 的地毯的信息,包含四个正整数a,b,g,k,每两个整数之间用一个空格隔开,分别表示铺设地毯的左下角的坐标(a,b)以及地毯在x轴和y 轴方向的长度。
第 n+2 行包含两个正整数x 和y,表示所求的地面的点的坐标(x,y)。
【输出】输出文件名为 carpet.out。
输出共 1 行,一个整数,表示所求的地毯的编号;若此处没有被地毯覆盖则输出-1。
【输入输出样例 1】【输入输出样例说明】如下图,1 号地毯用实线表示,2 号地毯用虚线表示,3 号用双实线表示,覆盖点(2,2)的最上面一张地毯是3 号地毯。
【输入输出样例 2】【输入输出样例说明】如上图,1 号地毯用实线表示,2 号地毯用虚线表示,3 号用双实线表示,点(4,5)没有被地毯覆盖,所以输出-1。
【数据范围】对于 30%的数据,有n≤2;对于 50%的数据,0≤a, b, g, k≤100;对于 100%的数据,有0≤n≤10,000,0≤a, b, g, k≤100,000。
【一句话题意】给定n个按顺序覆盖的矩形,求某个点最上方的矩形编号。
【考察知识点】枚举【思路】好吧我承认看到图片的一瞬间想到过二维树状数组和二维线段树。
置答案ans=-1,按顺序枚举所有矩形,如果点在矩形内则更新ans。
注意题中给出的不是对角坐标,实际上是(a,b)与(a+g,b+k)。
全国信息学奥林匹克联赛(NOIP2008)复赛普及组一.题目概览中文题目名称ISBN号码排座椅传球游戏立体图英文题目名称isbn seat ball drawing可执行文件名isbn seat ball drawing输入文件名isbn.in seat.in ball.in drawing.in输出文件名isbn.out seat.out ball.out drawing.out每个测试点时限1秒1秒1秒1秒测试点数目10 10 10 10每个测试点分值10 10 10 10比较方式全文比较全文比较全文比较全文比较题目类型传统传统传统传统二.提交源程序文件名对于pascal语言isbn.pas seat.pas ball.pas drawing.pas对于C语言isbn.c seat.c ball.c drawing.c对于C++语言isbn.cpp seat.cpp ball.cpp drawing.cpp三.编译命令(不包含任何优化开关)对于pascal语言fpc isbn.pas fpc seat.pas fpc ball.pas fpc drawing.pas对于C语言gcc –o isbnisbn.c gcc –o seatseat.c gcc –o ballball.c gcc –o drawingdrawing.c对于C++语言g++ –o isbnisbn.cpp g++ –o seatseat.cpp g++ –o ballball.cpp g++ –odrawingdrawing.cpp四.运行内存限制运行内存上限50M 50M 50M 50M注意事项:1、文件名(程序名和输入输出文件名)必须使用小写。
2、C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0。
3、全国统一评测时采用的机器配置为:CPU 1.9GHz,内存512M,上述时限以此配置为准。
全国信息学奥林匹克竞赛(NOIP2008)复赛普及组注意事项:1、文件名(程序名和输入输出文件名)必须使用小写。
2、C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0。
3、全国统一评测时采用的机器配置为:CPU 1.9GHz,内存512M,上述时限以此配置为准。
各省在自测时可根据具体配置调整时限。
1. ISBN号码(isbn.pas/c/cpp)【问题描述】每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”就是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。
ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔符后的五位数字代表该书在该出版社的编号;最后一位为识别码。
识别码的计算方法如下:首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod 11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。
例如ISBN号码0-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2,...,9,再求和,即0×1+6×2+……+2×9=158,然后取158 mod 11的结果4作为识别码。
你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出你认为是正确的ISBN号码。
4【输入】输入文件isbn.in只有一行,是一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。
【输出】输出文件isbn.out共一行,假如输入的ISBN号码的识别码正确,那么输出“Right”,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符“-”)。
全国信息学奥林匹克联赛(NOIP2008)复赛提高组一、题目概览二、提交源程序文件名三、编译命令(不包含任何优化开关)四、运行内存限制注意事项:1. 文件名(程序名和输入输出文件名)必须使用大写。
2. C/C++中函数main()的返回值类型必须是int,程序正常结束时的返回值必须是0。
3. 全国统一评测时采用的机器配置为:CPU 1.9GHz,内存512M,上述时限以此配置为准。
各省在自测时可根据具体配置调整时限。
1. 笨小猴(word.pas/c/cpp)【问题描述】笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。
但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn 是单词中出现次数最少的字母的出现次数,如果maxn-minn是一个质数,那么笨小猴就认为这是个Lucky Word,这样的单词很可能就是正确的答案。
【输入】输入文件word.in只有一行,是一个单词,其中只可能出现小写字母,并且长度小于100。
【输出】输出文件word.out共两行,第一行是一个字符串,假设输入的的单词是Lucky Word,那么输出“Lucky Word”,否则输出“No Answer”;第二行是一个整数,如果输入单词是Lucky Word,输出maxn-minn的值,否则输出0。
【输入输出样例1】【输入输出样例1解释】单词error中出现最多的字母r出现了3次,出现次数最少的字母出现了1次,3-1=2,2是质数。
【输入输出样例2】【输入输出样例2解释】单词olympic中出现最多的字母i出现了2次,出现次数最少的字母出现了1次,2-1=1,1不是质数。
基本的字符串处理,细心一点应该没问题的,不过判断素数时似乎需要考虑下0和1的情况。
var a:array['a'..'z']of integer;s:string;l,i,max,min,n:integer;ch:char;flag:boolean;beginassign(input,'word.in');reset(input);assign(output,'word.out');rewrite(output);readln(s);l:=length(s);fillchar(a,sizeof(a),0);for i:=1 to l doinc(a[s[i]]);max:=0;min:=100;for ch:='a'to 'z' doif a[ch]>0 then beginif a[ch]>max then max:=a[ch];if a[ch]<min then min:=a[ch];end;n:=max-min; flag:=true;if(n=0) or (n=1) then flag:=falseelsefor i:=2 to trunc(sqrt(n)) doif n mod i =0 then begin flag:=false;break;end;if flag then begin writeln('Lucky Word'); writeln(n);endelse begin writeln('No Answer');writeln(0);end;close(output);close(input);end.2. 火柴棒等式(matches.pas/c/cpp)【问题描述】给你n根火柴棍,你可以拼出多少个形如“A+B=C”的等式?等式中的A、B、C是用火柴棍拼出的整数(若该数非零,则最高位不能是0)。
用火柴棍拼数字0-9的拼法如图所示:注意:1. 加号与等号各自需要两根火柴棍2. 如果A≠B,则A+B=C与B+A=C视为不同的等式(A、B、C>=0)3. n根火柴棍必须全部用上【输入】输入文件matches.in共一行,又一个整数n(n<=24)。
【输出】输出文件matches.out共一行,表示能拼成的不同等式的数目。
【输入输出样例1】【输入输出样例1解释】2个等式为0+1=1和1+0=1。
【输入输出样例2】【输入输出样例2解释】9个等式为:0+4=40+11=111+10=112+2=42+7=94+0=47+2=910+1=1111+0=11预处理下,然后枚举、剪枝,范围稍微开大点,弄到2000似乎足够了,剪枝后不会超时的。
首先预处理下每个数(0~2000)需要多少个火柴棒,然后枚举A和B,再判断。
参考程序1:program matches;constinp='matches.in';oup='matches.out';num:array['0'..'9'] of integer=(6,2,5,5,4,5,6,3,7,6);//0~9需要的火柴棒数maxn=1000;varf:array[0..maxn*2] of longint;i,j,k,n,ans:longint;s:string;procedure flink;beginassign(input,inp);reset(input);assign(output,oup);rewrite(output);end;procedure fclose;beginclose(input);close(output);end;procedure init;//预处理0~2000每个数需要的火柴棒数vari,j,k:longint;s:string;beginfor i:= 0 to maxn*2 dobeginstr(i,s);f[i]:=0;for j:= 1 to length(s) doinc(f[i],num[s[j]]);end;end;beginflink;readln(n);init;ans:=0;n:=n-4;//总火柴棒数减去'+'和'='所需的火柴棒数for i:= 0 to maxn do//枚举Abeginif f[i]>=n then continue;//剪枝for j:= 0 to maxn do//枚举Bbeginif f[i]+f[j]>=n then continue;//剪枝k:=i+j;if f[i]+f[j]+f[k]=n then inc(ans);//符合条件,总数加一end;end;write(ans);fclose;end.参考程序2:program matches;var n:longint;beginassign(input,'matches.in');reset(input);assign(output,'matches.out');rewrite(output);read(n);n:=n-4;if n<9 thenbeginwriteln(0);close(output);exit;end;case n of9:writeln(1);10:writeln(2);11:writeln(8);12:writeln(9);13:writeln(6);14:writeln(9);15:writeln(29);16:writeln(39);17:writeln(38);18:writeln(65);19:writeln(88);20:writeln(128);end;close(output);end.3. 传纸条(massage.pas/c/cpp)【问题描述】小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。
一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。
幸运的是,他们可以通过传纸条来进行交流。
纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。
从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。
在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。
班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。
反之亦然。
还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然数来表示,数越大表示越好心。
小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。
现在,请你帮助小渊和小轩找到这样的两条路径。
【输入】输入文件message.in的第一行有2个用空格隔开的整数m和n,表示班里有m行n列(1<=m,n<=50)。
接下来的m行是一个m*n的矩阵,矩阵中第i行j列的整数表示坐在第i行j列的学生的好心程度。
每行的n个整数之间用空格隔开。
【输出】输出文件message.out共一行,包含一个整数,表示来回两条路上参与传递纸条的学生的好心程度之和的最大值。
【输入输出样例】【限制】30%的数据满足:1<=m,n<=10100%的数据满足:1<=m,n<=50这道题和方格取数是一样的,只是状态的给出不同而已,典型的动态规划,我们可以把一来一回变成2次同时从左上到右下的过程,用f(i1,j1,i2,j2)表示两个同时分别到达(i1,j1)(i2,j2)的最大值,则转移方程为:设x=max(f【i1-1,j1,i2-1,j2】,f【i1-1,j1,i2,j2-1】,f【i1,j1-1,i2-1,j2】,f【i1,j1-1,i2,j2-1】)f【i1,j1,i2,j2】={ 0 i1=0或j1=0或i2=0 或j2=0{ x+a【i1,j1】i1*i2*j1*j2<>0 且i1=i2,j1=j2{ x+a【i1,j1】+a【i2,j2】 i1*i2*j1*j2<>0 且i1<>i2,j1<>j2代码如下:program message;varf:array[0..51,0..51,0..51,0..51]of longint;map:array[0..100,0..100]of longint;n,m:longint;procedure init ;beginassign(input,'message.in');assign(output,'message.out');reset(input);rewrite(output);end;procedure prepare;vari,j:longint;beginreadln(n,m);for i:=1 to n dofor j:=1 to m dobeginread(map[i,j]);end;end;procedure outit;beginclose(input) ;close(output);end;procedure main;vari,j,k,l:longint;beginfor i:=1 to n dofor j:=1 to m dofor k:=1 to n dofor l:=1 to m dobeginif f[i-1,j,k-1,l]>f[i,j,k,l] thenf[i,j,k,l]:=f[i-1,j,k-1,l];if f[i-1,j,k,l-1]>f[i,j,k,l] thenf[i,j,k,l]:=f[i-1,j,k,l-1];if f[i,j-1,k-1,l]>f[i,j,k,l] thenf[i,j,k,l]:=f[i,j-1,k-1,l];if f[i,j-1,k,l-1]>f[i,j,k,l] thenf[i,j,k,l]:=f[i,j-1,k,l-1];f[i,j,k,l]:=f[i,j,k,l]+map[i,j];if (i<>k)and(j<>l) then f[i,j,k,l]:=f[i,j,k,l]+map[k,l]; end;writeln(f[n,m,n,m]);end;begininit;prepare;main;outit;end.var a:array[1..50,1..50] of integer;f:array[1..100,1..50,1..50]of integer;m,i,j,n,total,k,x1,x2:integer;function max(s1,s2,s3,s4:integer):integer;var s:integer;begins:=s1;if s2>s then s:=s2;if s3>s then s:=s3;if s4>s then s:=s4;max:=s;end;beginassign(input,'message.in');reset(input);assign(output,'message.out');rewrite(output);readln(m,n);for i:=1 to m dofor j:=1 to n doread(a[i,j]);fillchar(f,sizeof(f),0);for k:=2 to m+n-2 dofor x1:=1 to k dofor x2:=1 to x1-1 dobeginf[k,x1,x2]:=max(f[k-1,x1,x2],f[k-1,x1,x2-1],f[k-1,x1-1,x2],f[k-1,x1-1,x2-1]);f[k,x1,x2]:=f[k,x1,x2]+a[x1,k+1-x1]+a[x2,k+1-x2];end;writeln(f[m+n-2,m,m-1]);close(input);close(output);end.4. 双栈排序(twostack.pas/c/cpp)【问题描述】Tom最近在研究一个有趣的排序问题。