1、NOIP普及组复赛试题附题解noip2005普及组解题报告陶陶摘苹果【文件名】:apple.pas/c/cpp【问题描述】陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。现在已知10个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高度,请帮陶陶算一下她能够摘到的苹果的数目。假设她碰到苹果,苹果就会掉下来。【输入文件】输入文件apple.in包括两行数据。第一行包含10个100到200之间(包括100和200)的整数(以厘米为单位)分别表示10个苹果到地面的高度
2、,两个相邻的整数之间用一个空格隔开。第二行只包括一个100到120之间(包含100和120)的整数(以厘米为单位),表示陶陶把手伸直的时候能够达到的最大高度。【输出文件】输出文件apple.out包括一行,这一行只包含一个整数,表示陶陶能够摘到的苹果的数目。【样例输入】100200150140129134167198200111110【样例输出】5 分析:拿到这道题,我觉得还是比较简单的。由于数据范围都不超过200,用integer完全就足够了,具体步骤如下:1读入2循环1to103判断,找出最优解4输出【程序清单】programapple;vari,n,s:integer;a:array1.
3、10ofinteger;beginassign(input,apple.in);reset(input);fori:=1to10doread(ai);read(n);s:=0;fori:=1to10doifn+30=aithens:=s+1;close(input);assign(output,apple.out);rewrite(output);write(s);close(output);end.校门外的树【文件名】tree.pas/c/cpp【问题描述】某校大门外长度为L的马路上有一排树,每两棵相邻的树之间的间隔都是1米。我们可以把马路看成一个数轴,马路的一端在数轴0的位置,另一端在L的
4、位置;数轴上的每个整数点,即0,1,2,L,都种有一棵树。由于马路上有一些区域要用来建地铁。这些区域用它们在数轴上的起始点和终止点表示。已知任一区域的起始点和终止点的坐标都是整数,区域之间可能有重合的部分。现在要把这些区域中的树(包括区域端点处的两棵树)移走。你的任务是计算将这些树都移走后,马路上还有多少棵树。【输入文件】输入文件tree.in的第一行有两个整数L(1=L=10000)和M(1=M=100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。【输出文件】输出文件tree.out包
5、括一行,这一行只包含一个整数,表示马路上剩余的树的数目。【样例输入】5003150300100200470471【样例输出】298【数据规模】对于20%的数据,区域之间没有重合的部分;对于其它的数据,区域之间有重合的情况。分析:由于这道题存在着区域之间重合的情况,所以最好用一个数组表示状态,现将其全部置为1,若在区域之间就将其置为0。再在最后进行判断,计算值为1的个数。【程序清单】programtree;varb:array0.10000ofinteger;a:array1.500,1.2ofinteger;j,s,l,i,m:integer;beginassign(input,tree.in
6、);reset(input);assign(output,tree.out);rewrite(output);read(l,m);fori:=1tomdobeginread(ai,1);read(ai,2);end;fori:=0toldobi:=1;fori:=1tomdoforj:=ai,1toai,2dobj:=0;s:=0;fori:=0toldoifbi=1thens:=s+1;writeln(s);close(input);close(output);end.采药【文件名】:medic.pas/c/cpp【问题描述】辰辰是个天资聪颖的孩子,他的梦想是成为世界上最伟大的医师。为此,他
7、想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明的孩子,你应该可以让采到的草药的总价值最大。”如果你是辰辰,你能完成这个任务吗?【输入文件】输入文件medic.in的第一行有两个整数T(1=T=1000)和M(1=M=100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整数,分别表示采摘某株草
8、药的时间和这株草药的价值。【输出文件】输出文件medic.out包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。【样例输入】7037110069112【样例输出】3【数据规模】对于30%的数据,M=10;对于全部的数据,M=medi.time) and (medi.price+countlinej-medi.timecountlinej) thencountlinej:=medi.price+countlinej-medi.time;end;ans:=countlinet;end;beginindata;count;outdata;end.解法二:program
9、medic;varmax,t,m,i,j:Integer;a,b:array0.1000,0.1000ofinteger;beginassign(input,medic.in);reset(input);assign(output,medic.out);rewrite(output);read(t,m);fori:=1tomdobeginread(bi,1);read(bi,2);end;fori:=1tomdobeginforj:=1tobi,1-1doai,j:=ai-1,j;forj:=bi,1totdobeginif(bi,1=j)and(bi,2ai-1,j)thenai,j:=bi
10、,2;ifbi,2+ai-1,j-bi,1ai-1,jthenai,j:=bi,2+ai-1,j-bi,1elseai,j:=ai-1,j;end;end;writeln(am,t);close(input);close(output);end.circle.pas/c/cpp【问题描述】乐乐是一个聪明而又勤奋好学的孩子。他总喜欢探求事物的规律。一天,他突然对数的正整数次幂产生了兴趣。众所周知,2的正整数次幂最后一位数总是不断的在重复2,4,8,6,2,4,8,6我们说2的正整数次幂最后一位的循环长度是4(实际上4的倍数都可以说是循环长度,但我们只考虑最小的循环长度)。类似的,其余的数字的正整
11、数次幂最后一位数也有类似的循环现象:循环循环长度22、4、8、6433、9、7、1444、6255166177、9、3、1488、4、2、6499、12这时乐乐的问题就出来了:是不是只有最后一位才有这样的循环呢?对于一个整数n的正整数次幂来说,它的后k位是否会发生循环?如果循环的话,循环长度是多少呢?注意:1 如果n的某个正整数次幂的位数不足k,那么不足的高位看做是0。2 如果循环长度是L,那么说明对于任意的正整数a,n的a次幂和a + L次幂的最后k位都相同。【输入文件】输入文件circle.in只有一行,包含两个整数n(1 = n 10100)和k(1 = k = 100),n和k之间用一
12、个空格隔开,表示要求n的正整数次幂的最后k位的循环长度。【输出文件】输出文件circle.out包括一行,这一行只包含一个整数,表示循环长度。如果循环不存在,输出-1。【样例输入】32 2【样例输出】4【数据规模】对于30%的数据,k = 4;对于全部的数据,k = 100。刚刚看到这个题目,就知道要进行高精度的运算,这个地球人都知道。如果用直接模拟的算法,我们来计算一下时间复杂度。1、 每计算一次高精度乘法需要O(k2) /这个算法在网上有相关的优化,本人水平太差,没能掌握2、 总共需要进行至少L次高精度乘法,而L的最大值为10100。期望得分:30。由此,我们不得不对这个算法进行改进。请看
13、下面的推理。因为 如果循环长度是L,那么说明对于任意的正整数a,n的a次幂和a + L次幂的最后k位都相同。所以 如果循环长度是L,那么说明对于任意的正整数a,n的a次幂和a + L次幂的最后k-1位都相同。为了方便,我们把循环长度为K的时候对应的L记为F(K)。那么可以找出一个关系F(K)=m*F(K-1),其中m是整数。由抽屉原则,我们可以容易地想到,m=10。由此,我们可以从F(K-1)轻易模拟求出F(K)。需要说明的是,在求m的时候判断时要先乘上一个n。这样我们的算法就诞生了。它的时间复杂度是。实践证明,这个算法比传说中的标程要快好多。在我小小的C3 1.0G上面竟然只需要1.73s。
14、给出源代码:(写程序的时候没看原来的题目,变量名起得比较乱。)program circle;var start, /一开始的ntime, /每一次要向当前的运算结果上去乘的那个数。want,/其实want=start,具体的不同请看程序,want的作用是和now进行比对,检查是否找到了合适的mnow,/现在已经运算到的数ans:string; /答案add, /mn:integer; /ki:integer; procedure init;var s2,s:string; t:integer;beginassign(input,circle.in); reset(input);readln(s
15、);close(input);t:=pos( ,s);now:=copy(s,1,t-1);time:=now;want:=now;while length(want)101 do want:=0+want; /为了避免越界,在want前面加0(如果n的某个正整数次幂的位数不足k,那么不足的高位看做是0。)s2:=copy(s,t+1,255);val(s2,n,t);start:=copy(now,length(now)-n+1,255);end;function min(a,b:integer):integer;beginif a=b then min:=a else min:=b;end
16、;function multiply(a,b:string):string;/一个高精度乘高精度的functionvar a1,a2,a3:array1.128 of integer; k,t,l1,l2:integer;beginl1:=length(a); l2:=length(b);for t:=1 to l1 do a1t:=ord(al1-t+1)-48;for t:=1 to l2 do a2t:=ord(bl2-t+1)-48;fillchar(a3,sizeof(a3),0);for t:=1 to l1 do for k:=1 to min(103-t,l2) do inc(
17、a3t+k-1,a1t*a2k);t:=1;while t=10 then begininc(a3t+1,a3t div 10);a3t:=a3t mod 10;end;inc(t);end;a:=;k:=100; while a3k=0 do begin dec(k); if k=0 then break; end; /如果高精度的乘法结果只有0的话就直接输出0if k=0 then a:=0;while k0 do begina:=a+chr(48+a3k);dec(k);end;multiply:=a;end;function check(k:integer):boolean;/检查最后
18、k位是否已经得到了循环长度Lvar now2:string;beginnow2:=multiply(now,start);check:=(now2length(now2)-k+1=wantlength(want)-k+1)end;function mulinteger(a:string;b:integer):string;/高乘单var a1,a3:array1.128 of integer; t,k,l1:integer;beginl1:=length(a);for t:=1 to l1 do a1t:=ord(al1-t+1)-48;fillchar(a3,sizeof(a3),0);fo
19、r t:=1 to l1 do a3t:=a1t*b;t:=1;while t=10 then begin inc(a3t+1,a3t div 10); a3t:=a3t mod 10; end; inc(t);end;a:=;k:=100; while a3k=0 do dec(k);while k0 do begina:=a+chr(48+a3k);dec(k);end;mulinteger:=a;end;procedure noanswer;/无解beginassign(output,circle.out); rewrite(output);writeln(-1);close(output);halt;end;begininit;ans:=1;/F(0)=1i:=0;while (check(i+1)and(in) do inc(i); /如果第一位就像6那样自循环。if i10 then noanswer; until (check(i)and(add1); ans:=mulinteger(ans,add); while (check(i+1)and(i=n;assign(output,circle.out); rewrite(output);writeln(ans);close(output);end.
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1