NOIP初赛试题分类汇总完善程序部分.docx
《NOIP初赛试题分类汇总完善程序部分.docx》由会员分享,可在线阅读,更多相关《NOIP初赛试题分类汇总完善程序部分.docx(28页珍藏版)》请在冰豆网上搜索。
NOIP初赛试题分类汇总完善程序部分
NOIP初赛试题分类汇总_完善程序部分(总20页)
NOIP初赛试题汇总
完善程序
'2004
1.Joseph
题目描述:
原始的Joseph问题的描述如下:
有n个人围坐在一个圆桌周围,把这n个人依次编号为1,…,n。
从编号是1的人开始报数,数到第m个人出列,然后从出列的下一个人重新开始报数,数到第m个人又出列,…,如此反复直到所有的人全部出列为止。
比如当n=6,m=5的时候,出列的顺序依次是5,4,6,2,3,1。
现在的问题是:
假设有k个好人和k个坏人。
好人的编号的1到k,坏人的编号是k+1到2k。
我们希望求出m的最小值,使得最先出列的k个人都是坏人。
输入:
仅有的一个数字是k(0输出:
使得最先出列的k个人都是坏人的m的最小值。
输入样例:
4
输出样例:
30
程序:
#include<>
longk,m,begin;
intcheck(longremain){
longresult=(①)%remain;
if(②){
begin=result;return1;
}
elsereturn0;
}
intmain(){
longi,find=0;
scanf("%ld",&k);
for(m=k;③;m++){
find=1;begin=0;
for(i=0;iif(!
check(④)){
find=0;break;
}
}
printf("%ld\n",⑤);
return0;
}
2.逻辑游戏
题目描述:
一个同学给了我一个逻辑游戏。
他给了我图1,在这个图上,每一段边界都已经进行了编号。
我的任务是在图中画一条连续的曲线,使得这条曲线穿过每一个边界一次且仅穿过一次,而且曲线的起点和终点都在这整个区域的外面。
这条曲线是容许自交的。
对于图1,我的同学告诉我画出这样的一条曲线(图2)是不可能的,但是对于有的图形(比如图3),画出这样一条曲线是可行的。
对于给定的一个图,我想知道是否可以画出满足要求的曲线。
图1
图2
图3
图4
输入:
输入的图形用一个n×n的矩阵表示的。
矩阵的每一个单元里有一个0到255之间(包括0和255)的整数。
处于同一个区域的单元里的数相同,相邻区域的数不同(但是不相邻的区域里的数可能相同)。
输入的第一行是n(0以下的n行每行包括n个整数,分别给出对应的单元里的整数(这n个整数之间用空格分开)。
图4给出了输入样例对应的图形。
输出:
当可以画出满足题意的曲线的时候,输出“YES”;否则,输出“NO”。
输入样例:
3
112
122
112
输出样例:
YES
程序:
#include<>
#include<>
intorig,n,ns,a[102][102],bun;
intd[]={1,0,-1,0,0,1,①};
voidplimba(intx,inty){
inti,x1,y1;
a[x][y]=-a[x][y];
if(abs(a[x-1][y])!
=orig&&(②!
=a[x-1][y]
||abs(a[x][y-1])!
=orig))ns++;
if(abs(a[x+1][y])!
=orig&&(a[x+1][y-1]!
=a[x+1][y]
||abs(a[x][y-1])!
=orig))ns++;
if(abs(a[x][y-1])!
=orig&&(③!
=a[x][y-1]
||abs(a[x-1][y])!
=orig))ns++;
if(abs(a[x][y+1])!
=orig&&(a[x-1][y+1]!
=a[x][y+1]
||abs(a[x-1][y])!
=orig))ns++;
for(i=0;i<4;i++){
x1=x+d[2*i];y1=y+④;
if(x1>=1&&x1<=n&&y1>=1&&y1<=n&&⑤)
plimba(x1,y1);
}
}
intmain(){
inti,j;
bun=1;
scanf("%d",&n);
for(i=0;i<=n+1;i++)
for(j=0;j<=n+1;j++)a[i][j]=0;
a[0][0]=-1;a[n+1][0]=-1;
a[0][n+1]=-1;a[n+1][n+1]=-1;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)scanf("%d",&(a[i][j]));
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
if(a[i][j]>-1){
ns=0;⑥;
plimba(i,j);
if(ns%2==1)bun=0;
}
}
if(bun)printf("YES\n");elseprintf("NO\n");
return0;
}
'2005
1.木材加工
题目描述:
木材厂有一些原木,现在想把这些木头切割成一些长度相同的小段木头(木头有可能有
剩余),需要得到的小段的数目是给定了的。
当然,我们希望得到的小段越长越好,你的任
务是计算能够得到的小段木头的最大长度。
木头长度的单位是cm。
原木的长度都是正整数,我们要求切割得到的小段木头的长度
也是正整数。
输入:
第一行是两个正整数N和K(1≤N≤10000,1≤K≤10000),N是原木的数目,
K是需要得到的小段的数目。
接下来的N行,每行有一个1到10000之间的正整数,表示一根原木的长度。
输出:
输出能够切割得到的小段的最大长度。
如果连1cm长的小段都切不出来,输出”0”。
输入样例:
37
232
124
456
输出样例:
114
程序:
#include<>
intn,k,len[10000];
intisok(intt){
intnum=0,i;
for(i=0;iif(num>=k)break;
num=①;
}
if(②)return1;
elsereturn0;
}
intmain(){
inti,left,right,mid;
scanf("%d%d",&n,&k);
right=0;
for(i=0;iscanf("%d",&(len[i]));
if(right}
right++;
③;
while(④mid=(left+right)/2;
if(⑤)right=mid;
elseleft=mid;
}
printf("%d\n",left);
return0;
}
2.N叉树
题目描述:
我们都了解二叉树的先根遍历,中根遍历和后根遍历。
当知道先根遍历的结果和中根遍
历结果的时候,我们可以唯一的确定二叉树;同样的,如果知道了后根遍历的结果和中根遍
历结果,二叉树也是唯一确定的。
但是如果只知道先根遍历和后根遍历的结果,二叉树就不
是唯一的了。
但是我们可以计算满足条件的不同二叉树的一共有多少个。
这不是一个很困难
的问题,稍微复杂一点,我们把这个问题推广到N叉树。
我们用小写英文字母来表示N叉树的结点,不同的结点用不同的字母表示。
比如,对
于4叉树,如果先根遍历的结果是abdefgc,后根遍历的结果是defgbca,那么我们可以
得到6个不同的4叉树(如下图)。
输入:
输入数据包括3行。
第一行是一个正整数N(1≤N≤20),表示我们要考虑N叉树。
第二行和第三行分别是两个字符串序列,分别表示先根遍历和后根遍历的结果。
输出:
输出不同的N叉树的数目。
题目中给的数据保证得到的结果小于2
31
。
输入样例:
4
abdefgc
defgbca
输出样例:
6
程序:
#include<>
#include<>
charstr1[100],str2[100];
intN;
longcom[100][100];
longgetcom(intx,inty){
if(y==0||x==y)①;
elseif(com[x][y]!
=0)returncom[x][y];
else{
com[x][y]=getcom(x-1,y)+②;
returncom[x][y];
}
}
longcount(inta,intb,intc){
longsum=1;
intk=0;
ints=a+1,t=c,p;
if(a==b)return1;
while(s<=b){
p=t;
while(str1[s]!
=str2[t])t++;
sum=sum*count(s,s+t-p,p);
s=③;
④;
k++;
}
return⑤*getcom(N,k);
}
intmain(){
intlen;
scanf("%d",&N);
scanf("%s%s",str1,str2);
len=strlen(str1);
printf("%ld\n",count(⑥));
return0;
}
'2006
1.(选排列)下面程序的功能是利用递归方法生成从1到n(n<10)的n个数中取k(1<=k<=n)个数的
全部可能的排列(不一定按升序输出)。
例如,当n=3,k=2时,应该输出(每行输出5个排列):
1213212332
31
程序:
#include<>
intn,k,a[10];
longcount=0;
voidperm2(intj)
{inti,p,t;
if(①)
{for(i=k;i<=n;i++)
{count++;
t=a[k];a[k]=a[i];a[i]=t;
for(②)
printf("%1d",a[p]);/*"%1d"中是数字1,不是字母l*/
printf("");