1、明明的随机数(Noip2006)
【问题描述】
明明想在学校中请一些同学一起做一项问卷调查,为了实验的客观性,他先用计算机生成了N个1到1000之间的随机整数(N≤100),对于其中重复的数字,只保留一个,把其余相同的数去掉,不同的数对应着不同的学生的学号。然后再把这些数从小到大排序,按照排好的顺序去找同学做调查。请你协助明明完成“去重”与“排序”的工作。
【输入文件】
输入文件random.in 有2行,
第1行为1个正整数,表示所生成的随机数的个数:N
第2行有N个用空格隔开的正整数,为所产生的随机数。
【输出文件】
输出文件random.out 也是2行,第1行为1个正整数M,表示不相同的随机数的个数。第2行为M个用空格隔开的正整数,为从小到大排好序的不相同的随机数。
【输入样例】
   10
   20 40 32 67 40 20 89 300 400 15
【输出样例】
   8
   15 20 32 40 67 89 300 400
【参考程序】
//By LYLtim
var n,s:byte;
    i,min,max,x:word;
    b:array[1..1000]of boolean;
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;
    for i:=1 to n do
        begin
            read(x);
            b[x]:=true;
            if x<min then min:=x;
            if x>max then max:=x;
        end;
    close(input);
    for i:=min to max do if b[i] then inc(s);
    writeln(s);
    for i:=min to max do if b[i] then write(i,' ');
    close(output);
end.

2、车厢重组(carry.pas)
【问题描述】
在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转。一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序。于是他就负责用这座桥将进站的车厢按车厢号从小到大排列。他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序,输入初始的车厢顺序,计算最少用多少步就能将车厢排序。
【输入文件】
输入文件有两行数据,第一行是车厢总数N(不大于10000),第二行是N个不同的数表示初始的车厢顺序。
【输出文件】
一个数据,是最少的旋转次数。
【输入样例】carry .in
4
4 3 2 1
【输出样例】carry .out
6
【参考程序】
//By LYLtim
var n,i,j,t:word;
    a:array[1..10000]of word;
    change:boolean;
    s:longword;
begin
    assign(input,'carry.in');reset(input);
    assign(output,'carry.out');rewrite(output);
    readln(n);
    for i:=1 to n do read(a[i]);
    close(input);
    s:=0;i:=1;
    repeat
        change:=false;
        for j:=1 to n-i do
            if a[j]>a[j+1] then
                begin
                    t:=a[j];a[j]:=a[j+1];a[j+1]:=t;
                    change:=true;
                    inc(s);
                end;
    until not change;
    writeln(s);
    close(output);
end.

3、众数(masses.pas)
【问题描述】
    由文件给出N个1到30000间无序数正整数,其中1≤N≤10000,同一个正整数可能会出现多次,出现次数最多的整数称为众数。求出它的众数及它出现的次数。
【输入格式】
    输入文件第一行是正整数的个数N,第二行开始为N个正整数。
【输出格式】
    输出文件有若干行,每行两个数,第1个是众数,第2个是众数出现的次数。
【输入样例】masses.in
12
2 4 2 3 2 5 3 7 2 3 4 3
【输出样例】masses.out
2   4
3   4
【参考程序】
//By LYLtim
var n,i,x,min,max,maxx:word;
    a:array[1..30000]of word;
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);
    for i:=1 to n do
        begin
            read(x);
            if x<min then min:=x;
            if x>max then max:=x;
            inc(a[x]);
            if a[x]>maxx then maxx:=a[x];
        end;
    for i:=min to max do if a[i]=maxx then writeln(i,' ',a[i]);
    close(input);close(output);
end.

4、第k小整数(knunber.pas)
【问题描述】
    现有n个正整数,n≤10000,要求出这n个正整数中的第k个最小整数(相同大小的整数只计算一次),k≤1000,正整数均小于30000。
【输入格式】
    第一行为n和k,第二行开始为n个正整数的值,整数间用空格隔开。
【输出格式】
    第k个最小整数的值;若无解,则输出“NO RESULT”。
【输入样例】knunber.in
10 3
1 3 3 7 2 5 1 2 4 6
【输出样例】knunber.out
    3
【参考程序】
//By LYLtim
var n,k,i,x,min,max,s:word;
    b:array[1..30000]of boolean;
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);
    for i:=1 to n do
        begin
            read(x);
            b[x]:=true;
            if x<min then min:=x;
            if x>max then max:=x;
        end;
    close(input);
    for i:=min to max do
        begin
            if b[i] then inc(s);
            if s=k then begin writeln(i); close(output); halt; end;
        end;
    writeln('NO RESULT');
    close(output);
end.

5、军事机密(Secret.pas)
【问题描述】
军方截获的信息由n(n<=30000)个数字组成,因为是敌国的高端秘密,所以一时不能破获。最原始的想法就是对这n个数进行小到大排序,每个数都对应一个序号,然后对第i个是什么数感兴趣,现在要求编程完成。
【输入格式】
    第一行n,接着是n个截获的数字,接着一行是数字k,接着是k行要输出数的序号。
【输出格式】
    k行序号对应的数字。
【输入样例】Secret.in
5
121 1 126 123   7
3
2
4
3
【输出样例】Secret.out
7
123
121
【参考程序】
//By LYLtim
var n,i,k:word;
    a:array[1..30000]of longword;

procedure qsort(l,r:longword);
    var pl,pr,m,t:longword;
    begin
        pl:=l;pr:=r;m:=a[(l+r)shr 1];
        repeat
            while a[pl]<m do inc(pl);
            while a[pr]>m do dec(pr);
            if pl<=pr then
                begin
                    t:=a[pl];a[pl]:=a[pr];a[pr]:=t;
                    inc(pl);dec(pr);
                end;
        until pl>pr;
        if pl<r then qsort(pl,r);
        if pr>l then qsort(l,pr);
    end;{qsort}

begin{main}
    assign(input,'secret.in');reset(input);
    assign(output,'secret.out');rewrite(output);
    readln(n);
    for i:=1 to n do read(a[i]);
    qsort(1,n);
    readln(k);
    for i:=1 to k do begin readln(n); writeln(a[n]); end;
    close(input);close(output);
end.

6、奖学金(Noip2007)
【问题描述】
某小学最近得到了一笔赞助,打算拿出其中一部分为学习成绩优秀的前5名学生发奖学金。期末,每个学生都有3门课的成绩:语文、数学、英语。先按总分从高到低排序,如果两个同学总分相同,再按语文成绩从高到低排序,如果两个同学总分和语文成绩都相同,那么规定学号小的同学排在前面,这样,每个学生的排序是唯一确定的。
任务:先根据输入的3门课的成绩计算总分,然后按上述规则排序,最后按排名顺序输出前5名学生的学号和总分。注意,在前5名同学中,每个人的奖学金都不相同,因此,你必须严格按上述规则排序。例如,在某个正确答案中,如果前两行的输出数据(每行输出两个数:学号、总分)是:
7 279
5 279
这两行数据的含义是:总分最高的两个同学的学号依次是7号、5号。这两名同学的总分都是279(总分等于输入的语文、数学、英语三科成绩之和),但学号为7的学生语文成绩更高一些。如果你的前两名的输出数据是:5 279
7 279
则按输出错误处理,不能得分。
【输入格式】
输入文件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

90 67 80

87 66 91

78 89 91

88 99 77

67 89 64

78 89 98

6 265

4 264

3 258

2 244

1 237

【输入输出样例2】

scholar.in

scholar.out

8

80 89 89

88 98 78

90 67 80

87 66 91

78 89 91

88 99 77

67 89 64

78 89 98

8 265

2 264

6 264

1 258

5 258

【限制】
    50%的数据满足:各学生的总成绩各不相同
100%的数据满足:6<=n<=300
【参考程序】
//By LYLtim
type
    node=record i,ch:byte; sum:word; end;
    arr=array[1..300]of node;
var n:word;
    stu:arr;
    ma,en:byte;

procedure init;
var i:word;
begin
    assign(input,'scholar.in');reset(input);
    readln(n);
    for i:=1 to n do
        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}

procedure merge(l,m,r:word);
var pt,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
            begin tmp[pt]:=stu[pl]; inc(pt); inc(pl); end
        else begin tmp[pt]:=stu[pr]; inc(pt); inc(pr); end;
    while pl<=m do begin tmp[pt]:=stu[pl]; inc(pt); inc(pl); end;
    while pr<=r do begin tmp[pt]:=stu[pr]; inc(pt); inc(pr); end;
    for pt:=l to r do stu[pt]:=tmp[pt];
end;{merge}

procedure mergesort(l,r:word);
var m:word;
begin
    if l>=r then exit;
    m:=(l+r)>>1;
    mergesort(l,m);
    mergesort(m+1,r);
    merge(l,m,r);
end;{mergesort}

procedure print;
var i:byte;
begin
    assign(output,'scholar.out');rewrite(output);
    for i:=1 to 5 do writeln(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

2 3

4 2

5 1

100 2

【限制】
    40%的数据满足:1<=n<=1000
    80%的数据满足:1<=n<=50000
    100%的数据满足:1<=n<=200000,每个数均不超过1 500 000 000(1.5*109)
【参考程序】
//By LYLtim
var n:longword;
    a:array[1..200001]of longint;

procedure init;
var i:longword;
begin
    assign(input,'count.in');reset(input);
    readln(n);
    for i:=1 to n do readln(a[i]);
    close(input);
end;{init}

procedure qsort(l,r:longword);
var pl,pr,m,t:longint;
begin
    pl:=l;pr:=r;m:=a[(l+r)>>1];
    repeat
        while a[pl]<m do inc(pl);
        while a[pr]>m do dec(pr);
        if pl<=pr then
            begin
                t:=a[pl];a[pl]:=a[pr];a[pr]:=t;
                inc(pl);dec(pr);
            end;
    until pl>=pr;
    if pl<r then qsort(pl,r);
    if pr>l then qsort(l,pr);
end;{qsort}

procedure work;
var i,k:longword;
begin
    assign(output,'count.out');rewrite(output);
    a[n+1]:=maxlongint;
    k:=1;
    for i:=2 to n+1 do
        if a[i]<>a[i-1] then begin writeln(a[i-1],' ',k); k:=1; end
        else inc(k);
    close(output);
end;{work}

begin{main}
    init;
    qsort(1,n);
    work;
end.

posted on 2011-08-05 11:01  shallyzhang  阅读(1102)  评论(0)    收藏  举报