完整word版排序例题.docx
《完整word版排序例题.docx》由会员分享,可在线阅读,更多相关《完整word版排序例题.docx(13页珍藏版)》请在冰豆网上搜索。
完整word版排序例题
1、明明的随机数(Noip2006)
【问题描述】
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。
然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。
请你协助明明完成“去重”与“排序”的工作。
【输入文件】
输入文件random.in有2行,
第1行为1个正整数,表示所生成的随机数的个数:
N
第2行有N个用空格隔开的正整数,为所产生的随机数。
【输出文件】
输出文件random.out也是2行,第1行为1个正整数M,表示不相同的随机数的个数。
第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。
【输入样例】
10
2040326740208930040015
【输出样例】
8
152032406789300400
【参考程序】
//ByLYLtim
varn,s:
byte;
i,min,max,x:
word;
b:
array[1..1000]ofboolean;
begin
assign(input,'random.in');reset(input);
assign(output,'random.out');rewrite(output);
readln(n);
fillchar(b,sizeof(b),false);
min:
=1000;max:
=0;s:
=0;
fori:
=1tondo
begin
read(x);
b[x]:
=true;
ifx=x;
ifx>maxthenmax:
=x;
end;
close(input);
fori:
=mintomaxdoifb[i]theninc(s);
writeln(s);
fori:
=mintomaxdoifb[i]thenwrite(i,'');
close(output);
end.
2、车厢重组(carry.pas)
【问题描述】
在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转。
一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序。
于是他就负责用这座桥将进站的车厢按车厢号从小到大排列。
他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序,输入初始的车厢顺序,计算最少用多少步就能将车厢排序。
【输入文件】
输入文件有两行数据,第一行是车厢总数N(不大于10000),第二行是N个不同的数表示初始的车厢顺序。
【输出文件】
一个数据,是最少的旋转次数。
【输入样例】carry.in
4
4321
【输出样例】carry.out
6
【参考程序】
//ByLYLtim
varn,i,j,t:
word;
a:
array[1..10000]ofword;
change:
boolean;
s:
longword;
begin
assign(input,'carry.in');reset(input);
assign(output,'carry.out');rewrite(output);
readln(n);
fori:
=1tondoread(a[i]);
close(input);
s:
=0;i:
=1;
repeat
change:
=false;
forj:
=1ton-ido
ifa[j]>a[j+1]then
begin
t:
=a[j];a[j]:
=a[j+1];a[j+1]:
=t;
change:
=true;
inc(s);
end;
untilnotchange;
writeln(s);
close(output);
end.
3、众数(masses.pas)
【问题描述】
由文件给出N个1到30000间无序数正整数,其中1≤N≤10000,同一个正整数可能会出现多次,出现次数最多的整数称为众数。
求出它的众数及它出现的次数。
【输入格式】
输入文件第一行是正整数的个数N,第二行开始为N个正整数。
【输出格式】
输出文件有若干行,每行两个数,第1个是众数,第2个是众数出现的次数。
【输入样例】masses.in
12
242325372343
【输出样例】masses.out
2 4
3 4
【参考程序】
//ByLYLtim
varn,i,x,min,max,maxx:
word;
a:
array[1..30000]ofword;
begin
assign(input,'masses.in');reset(input);
assign(output,'masses.out');rewrite(output);
fillchar(a,sizeof(a),0);
min:
=30000;max:
=0;maxx:
=0;
readln(n);
fori:
=1tondo
begin
read(x);
ifx=x;
ifx>maxthenmax:
=x;
inc(a[x]);
ifa[x]>maxxthenmaxx:
=a[x];
end;
fori:
=mintomaxdoifa[i]=maxxthenwriteln(i,'',a[i]);
close(input);close(output);
end.
4、第k小整数(knunber.pas)
【问题描述】
现有n个正整数,n≤10000,要求出这n个正整数中的第k个最小整数(相同大小的整数只计算一次),k≤1000,正整数均小于30000。
【输入格式】
第一行为n和k,第二行开始为n个正整数的值,整数间用空格隔开。
【输出格式】
第k个最小整数的值;若无解,则输出“NORESULT”。
【输入样例】knunber.in
103
1337251246
【输出样例】knunber.out
3
【参考程序】
//ByLYLtim
varn,k,i,x,min,max,s:
word;
b:
array[1..30000]ofboolean;
begin
assign(input,'knumber.in');reset(input);
assign(output,'knumber.out');rewrite(output);
fillchar(b,sizeof(b),false);
min:
=30000;max:
=0;s:
=0;
readln(n,k);
fori:
=1tondo
begin
read(x);
b[x]:
=true;
ifx=x;
ifx>maxthenmax:
=x;
end;
close(input);
fori:
=mintomaxdo
begin
ifb[i]theninc(s);
ifs=kthenbeginwriteln(i);close(output);halt;end;
end;
writeln('NORESULT');
close(output);
end.
5、军事机密(Secret.pas)
【问题描述】
军方截获的信息由n(n<=30000)个数字组成,因为是敌国的高端秘密,所以一时不能破获。
最原始的想法就是对这n个数进行小到大排序,每个数都对应一个序号,然后对第i个是什么数感兴趣,现在要求编程完成。
【输入格式】
第一行n,接着是n个截获的数字,接着一行是数字k,接着是k行要输出数的序号。
【输出格式】
k行序号对应的数字。
【输入样例】Secret.in
5
1211126123 7
3
2
4
3
【输出样例】Secret.out
7
123
121
【参考程序】
//ByLYLtim
varn,i,k:
word;
a:
array[1..30000]oflongword;
procedureqsort(l,r:
longword);
varpl,pr,m,t:
longword;
begin
pl:
=l;pr:
=r;m:
=a[(l+r)shr1];
repeat
whilea[pl] whilea[pr]>mdodec(pr);
ifpl<=prthen
begin
t:
=a[pl];a[pl]:
=a[pr];a[pr]:
=t;
inc(pl);dec(pr);
end;
untilpl>pr;
ifpl ifpr>lthenqsort(l,pr);
end;{qsort}
begin{main}
assign(input,'secret.in');reset(input);
assign(output,'secret.out');rewrite(output);
readln(n);
fori:
=1tondoread(a[i]);
qsort(1,n);
readln(k);
fori:
=1tokdobeginreadln(n);writeln(a[n]);end;
close(input);close(output);
end.
6、奖学金(Noip2007)
【问题描述】
某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。
期末,每个学生都有3门课的成绩:
语文、数学、英语。
先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面,这样,每个学生的排序是唯一确定的。
任务:
先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前5名学生的学号和总分。
注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。
例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:
学号、总分)是:
7279
5279
这两行数据的含义是:
总分最高的两个同学的学号依次是7号、5号。
这两名同学的总分都是279(总分等于输入的语文、数学、英语三科成绩之和),但学号为7的学生语文成绩更高一些。
如果你的前两名的输出数据是:
5279
7279
则按输出错误处理,不能得分。
【输入格式】
输入文件scholar.in包含n+1行:
第1行为一个正整数n,表示该校参加评选的学生人数。
第2到n+1行,每行有3个用空格隔开的数字,每个数字都在0到100之间。
第j行的3个数字依次表示学号为j-1的学生的语文、数学、英语的成绩。
每个学生的学号按照输入顺序编号为1~n(恰好是输入数据的行号减1)。
所给的数据都是正确的,不必检验。
【输出格式】
输出文件scholar.out共有5行,每行是两个用空格隔开的正整数,依次表示前5名学生的学号和总分。
【输入输出样例1】
scholar.in
scholar.out
6
906780
876691
788991
889977
678964
788998
6265
4264
3258
2244
1237
【输入输出样例2】
scholar.in
scholar.out
8
808989
889878
906780
876691
788991
889977
678964
788998
8265
2264
6264
1258
5258
【限制】
50%的数据满足:
各学生的总成绩各不相同
100%的数据满足:
6<=n<=300
【参考程序】
//ByLYLtim
type
node=recordi,ch:
byte;sum:
word;end;
arr=array[1..300]ofnode;
varn:
word;
stu:
arr;
ma,en:
byte;
procedureinit;
vari:
word;
begin
assign(input,'scholar.in');reset(input);
readln(n);
fori:
=1tondo
begin
stu[i].i:
=i;
read(stu[i].ch);readln(ma,en);
stu[i].sum:
=stu[i].ch+ma+en;
end;
close(input);
end;{init}
proceduremerge(l,m,r:
word);
varpt,pl,pr:
word;
tmp:
arr;
begin
pt:
=l;pl:
=l;pr:
=m+1;
while(pl<=m)and(pr<=r)do
if(stu[pl].sum>stu[pr].sum)or(stu[pl].sum=stu[pr].sum)and(stu[pl].ch>=stu[pr].ch)then
begintmp[pt]:
=stu[pl];inc(pt);inc(pl);end
elsebegintmp[pt]:
=stu[pr];inc(pt);inc(pr);end;
whilepl<=mdobegintmp[pt]:
=stu[pl];inc(pt);inc(pl);end;
whilepr<=rdobegintmp[pt]:
=stu[pr];inc(pt);inc(pr);end;
forpt:
=ltordostu[pt]:
=tmp[pt];
end;{merge}
proceduremergesort(l,r:
word);
varm:
word;
begin
ifl>=rthenexit;
m:
=(l+r)>>1;
mergesort(l,m);
mergesort(m+1,r);
merge(l,m,r);
end;{mergesort}
procedureprint;
vari:
byte;
begin
assign(output,'scholar.out');rewrite(output);
fori:
=1to5dowriteln(stu[i].i,'',stu[i].sum);
close(output);
end;{print}
begin{main}
init;
mergesort(1,n);
print;
end.
7、统计数字(Noip2007)
【问题描述】
某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109)。
已知不相同的数不超过10000个,现在需要统计这些自然数各自出现的次数,并按照自然数从小到大的顺序输出统计结果。
【输入格式】
输入文件count.in包含n+1行:
第1行是整数n,表示自然数的个数。
第2~n+1行每行一个自然数。
【输出格式】
输出文件count.out包含m行(m为n个自然数中不相同数的个数),按照自然数从小到大的顺序输出。
每行输出两个整数,分别是自然数和该数出现的次数,其间用一个空格隔开。
【输入输出样例】
count.in
count.out
8
2
4
2
4
5
100
2
100
23
42
51
1002
【限制】
40%的数据满足:
1<=n<=1000
80%的数据满足:
1<=n<=50000
100%的数据满足:
1<=n<=200000,每个数均不超过1500000000(1.5*109)
【参考程序】
//ByLYLtim
varn:
longword;
a:
array[1..200001]oflongint;
procedureinit;
vari:
longword;
begin
assign(input,'count.in');reset(input);
readln(n);
fori:
=1tondoreadln(a[i]);
close(input);
end;{init}
procedureqsort(l,r:
longword);
varpl,pr,m,t:
longint;
begin
pl:
=l;pr:
=r;m:
=a[(l+r)>>1];
repeat
whilea[pl] whilea[pr]>mdodec(pr);
ifpl<=prthen
begin
t:
=a[pl];a[pl]:
=a[pr];a[pr]:
=t;
inc(pl);dec(pr);
end;
untilpl>=pr;
ifpl ifpr>lthenqsort(l,pr);
end;{qsort}
procedurework;
vari,k:
longword;
begin
assign(output,'count.out');rewrite(output);
a[n+1]:
=maxlongint;
k:
=1;
fori:
=2ton+1do
ifa[i]<>a[i-1]thenbeginwriteln(a[i-1],'',k);k:
=1;end
elseinc(k);
close(output);
end;{work}
begin{main}
init;
qsort(1,n);
work;
end.
分数(mark):
【问题描述】
问题描述:
高考分数刚刚公布,共有N个人参加考试,为了有便于填写志愿,教育部把所有考生的成绩平均分成m档。
保证n是m的倍数。
考试成绩在(k-1)*(n/m)+1名到k*(n/m)名的考生被分配到K档(k=1,2,3…m)。
并列第i名的所有考生都被分配到K挡(k=1,2,3…m),并列i名的所有考生都算i名。
小Y刚参加完了高考,迫切的想知道自己被分在第几挡,你能帮助他吗?
输入格式:
第一行两个整数n,m<=1000,保证n是m的倍数。
接下来n行,每行一个整数Ai,表示第i个考生的成绩。
最后一行,一个整数x,1<=x<=n,表示询问第i个考生被分在那一档。
输出格式:
一行一个数字,表示它被分在那一档。
输入样例:
63
632
651
624
3
先找出要查找的分数,然后找出比这个分数大的分数的个数,然后它加1就是名次,最后根据归着得出档次;
Varn.m,I,j,x,t,ans:
longint;
A,num,rank:
array[0..100]oflongint;
Begin
Assign(input,’mark.in’);
Assign(output,’mark.out’);
Reset(input);
Rewrite(output);
Readln(n,m);
Fori:
=1tondobegin
Read(a[i]),num[i]:
=I;
End;
Readln(x);
Fori:
=1ton-1do
Forj:
=i+1tondo
Ifa[i]=a[i];
A[i]:
=a[j];
A[j]:
=t;
Num[i]:
=num[j];
Num[j]:
=t;
Emd;
Rank[1]:
=1;
Fori:
=2tondo
Begin
Ifa[i]=a[i-1]thenrank[i]:
=rank[i-1]
Elserank[i]:
=i+1;
Ifnum[i]=xthenbeginans:
=rank[i];break;end;
Writeln(ansdiv(ndivm)+1);
Close(input);
Close(output);
End;