noip复赛总结归纳(2010至2015年c++普及组复赛试题)一、【题目】1.数字统计(two.pas/c/cpp)【问题描述】请统计某个给定范围[L,R]的所有整数中,数字2出现的次数。比如给定范围[2,22],数字2在数2中出现了1次,在数12中出现1次,在数20中出现1次,在数21中出现1次,在数22中出现2次,所以数字2在该范围内一共出现了6次。【输入】输入文件名为two.in。输入共1行,为两个正整数L和R,之间用一个空格隔开。【输出】输出文件名为two.out。输出共1行,表示数字2出现的次数。【输入输出样例1】two.intwo.out2226【输入输出样例2】two.intwo.out210020【数据范围】1≤L≤R≤10000。【算法】把每一位分出来,一一判断【代码】#includecstdiousingnamespacestd;intmain(){intr,l,ans=0;scanf(%d%d,&r,&l);for(inti=r;i=l;i++)//一一判断{intnum=i;while(num0)//把每一位分离{if(num%10==2)ans++;num/=10;}}printf(%d,ans);return0;}【年份】2010二、【题目】2.接水问题(water.pas/c/cpp)【问题描述】学校里有一个水房,水房里一共装有m个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为1。现在有n名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从1到n编号,i号同学的接水量为wi。接水开始时,1到m号同学各占一个水龙头,并同时打开水龙头接水。当其中某名同学j完成其接水量要求wj后,下一名排队等候接水的同学k马上接替j同学的位置开始接水。这个换人的过程是瞬间完成的,且没有任何水的浪费。即j同学第x秒结束时完成接水,则k同学第x+1秒立刻开始接水。若当前接水人数n’不足m,则只有n’个龙头供水,其它m-n’个龙头关闭。现在给出n名同学的接水量,按照上述接水规则,问所有同学都接完水需要多少秒。【输入】输入文件名为water.in。第1行2个整数n和m,用一个空格隔开,分别表示接水人数和龙头个数。第2行n个整数w1、w2、……、wn,每两个整数之间用一个空格隔开,wi表示i号同学的接水量。【输出】输出文件名为water.out。输出只有一行,1个整数,表示接水所需的总时间。【输入输出样例1】water.inwater.out53444121【输入输出样例1说明】第1秒,3人接水。第1秒结束时,1、2、3号同学每人的已接水量为1,3号同学接完水,4号同学接替3号同学开始接水。第2秒,3人接水。第2秒结束时,1、2号同学每人的已接水量为2,4号同学的已接水量为1。第3秒,3人接水。第3秒结束时,1、2号同学每人的已接水量为3,4号同学的已接水量为2。4号i同学接完水,5号同学接替4号同i学开始接水。第4秒,3人接水。第4秒结束时,1、2号同学每人的已接水量为4,5号同学的已接水量为1。1、2、5号i同学接完水,即所有人完成接水。总接水时间为4秒。【输入输出样例2】water.inwater.out842371873270938076163【数据范围】1≤n≤10000,1≤m≤100且m≤n;1≤wi≤100。【算法】把人数分为两部分,一人对一个水龙头,作为第一部分,剩下是第二部分的,每一次从第一部分找一个时间最少人,把第二部分的一个人加进去。【代码】#includestdio.hintw[10005];intmain(){inti,j,m,n;scanf(%d%d,&m,&n);for(i=1;i=m;i++)//输入1到m的数据到w[i]scanf(%d,&w[i]);for(i=n+1;i=m;i++){intk=1;//假设w[k]=w[1]是最小for(j=2;j=n;j++)if(w[k]w[j])k=j;w[k]+=w[i];}intk=1;for(i=2;i=n;i++)if(w[k]w[i])k=i;printf(%d,w[k]);return0;}【年份】2010三、【题目】三国游戏(sanguo.pas/c/cpp)【问题描述】小涵很喜欢电脑游戏,这些天他正在玩一个叫做《三国》的游戏。在游戏中,小涵和计算机各执一方,组建各自的军队进行对战。游戏中共有N位武将(N为偶数且不小于4),任意两个武将之间有一个“默契值”,表示若此两位武将作为一对组合作战时,该组合的威力有多大。游戏开始前,所有武将都是自由的(称为自由武将,一旦某个自由武将被选中作为某方军队的一员,那么他就不再是自由武将了),换句话说,所谓的自由武将不属于任何一方。游戏开始,小涵和计算机要从自由武将中挑选武将组成自己的军队,规则如下:小涵先从自由武将中选出一个加入自己的军队,然后计算机也从自由武将中选出一个加入计算机方的军队。接下来一直按照“小涵→计算机→小涵→……”的顺序选择武将,直到所有的武将被双方均分完。然后,程序自动从双方军队中各挑出一对默契值最高的武将组合代表自己的军队进行二对二比武,拥有更高默契值的一对武将组合获胜,表示两军交战,拥有获胜武将组合的一方获胜。已知计算机一方选择武将的原则是尽量破坏对手下一步将形成的最强组合,它采取的具体策略如下:任何时刻,轮到计算机挑选时,它会尝试将对手军队中的每个武将与当前每个自由武将进行一一配对,找出所有配对中默契值最高的那对武将组合,并将该组合中的自由武将选入自己的军队。下面举例说明计算机的选将策略,例如,游戏中一共有6个武将,他们相互之间的默契值如下表所示双方选将过程如下所示:小涵轮到计算机时可选的自由武将计算机计算机选将说明第一轮5123464小涵手中5号武将与4号的默契值昀高,所以选择4号第二轮5312641小涵手中的5号和3号武将与自由武将中配对可产生的昀大默契值为29,是由5号与1号配对产生的,因此计算机选择1号第三轮5362412小涵想知道,如果计算机在一局游戏中始终坚持上面这个策略,那么自己有没有可能必胜?如果有,在所有可能的胜利结局中,自己那对用于比武的武将组合的默契值最大是多少?假设整个游戏过程中,对战双方任何时候均能看到自由武将队中的武将和对方军队的武将。为了简化问题,保证对于不同的武将组合,其默契值均不相同。【输入】输入文件名为sanguo.in,共N行。第一行为一个偶数N,表示武将的个数。第2行到第N行里,第(i+1)行有(N?i)个非负整数,每两个数之间用一个空格隔开,表示i号武将和i+1,i+2,……,N号武将之间的默契值(0≤默契值≤1,000,000,000)。【输出】输出文件sanguo.out共1或2行。若对于给定的游戏输入,存在可以让小涵获胜的选将顺序,则输出1,并另起一行输出所有获胜的情况中,小涵最终选出的武将组合的最大默契值。如果不存在可以让小涵获胜的选将顺序,则输出0。【输入输出样例1】sanguo.insanguo.out652816292723320183226331112132【输入输出样例说明】首先小涵拿走5号武将;计算机发现5号武将和剩下武将中的4号默契值最高,于是拿走4号;小涵接着拿走3号;计算机发现3、5号武将之一和剩下的武将配对的所有组合中,5号和1号默契值最高,于是拿走1号;小涵接着拿走2号;计算机最后拿走6号。在小涵手里的2,3,5号武将中,3号和5号配合最好,默契值为32,而计算机能推出的最好组合为1号和6号,默契值为27。结果为小涵胜,并且这个组合是小涵用尽所有方法能取到的最好组合。【输入输出样例2】sanguo.insanguo.out842241029271258318162680625336115332017131577945019177【数据范围】对于40%的数据有N≤10。对于70%的数据有N≤18。对于100%的数据有N≤500。【算法】每个武将先找第一大,删掉,再找第一大(就是找第二大),看看是否比现有答案大。人是必胜的,直接输1和答案。【代码】#includeiostream#includecmath#includecstdio#includecstring#includealgorithmusingnamespacestd;intn,a[1000][1000],ans,maxx;intmain(){scanf(%d,&n);for(inti=1;i=n-1;i++)//输入,a作为邻接矩阵{for(intj=i+1;j=n;j++){if(i==j)continue;scanf(%d,&a[i][j]);a[j][i]=a[i][j];}}for(inti=1;i=n;i++){for(intj=1;j=n;j++){if(a[i][j]a[i][maxx])maxx=j;}a[i][maxx]=0;for(intj=1;j=n;j++)ans=max(ans,a[i][j]);maxx=1;}printf(1\n%d,ans);return0;}【年份】2010四、【题目】1.数字反转(reverse.cpp/c/pas)【问题描述】给定一个整数,请将该数各个位上数字反转得到一个新数。新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例2)。【输入】输入文件名为reverse.in。输入共1行,一个整数N。【输出】输出文件名为reverse.out。输出共1行,一个整数,表示反转后的新数。【输入输出样例1】123321【输入输出样例2】-380-83【数据范围】-1,000,000,000≤N≤1,000,000,000。【算法】其实就是逆序输出一个字符串,但要判断正负,特判0,另外要删除前导0。这题就是考字符串思想。【代码】#includeiostream#includecmath#includecstdio#includecstring#includealgorithmusingnamespacestd;intmain(){chara[20120];gets(a);intb,len=strlen(a);if(a[0]=='0'){cout0;return0;}if(a[0]=='-')cout'-';boolf=0;for(inti=len-1;i=0;i--)if((f==1||a[i]!='0')&&a[i]!='-')couta[i],f=1;return0;}【年份】2011五、【题目】2.统计单词数(stat.cpp/c/pas)【问题描述】一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同(参见样例1),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2)。【输入】输入文件名为stat.in,2行。第1行为一个字符串,其中只含字母,表示给定单词;第2行为一个字符串,其中只可能包含字母和空格,表示给定的文章。【输出】输出文件名为stat.out。只有一行,如果在文章中找到给定单词则输出两个整数,两个整数之间用一个空格隔开,分别是单词在文章中出现的次数和第一次出现的位置(即在文章中第一次出现时,单词首字母在文章中的位置,位置从0开始);如果单词在文章中没有出现,则直接输出一个整数-1。【输入输出样例1】stat.instat.outTotobeornottobeisaquestion20【输入输出样例1说明】输出结果表示给定的单词To在文章中出现两次,第一次出现的位置为0。【输入输出样例2】stat.instat.o