【第一层级 条件反射】
1、个十百千各数位的求法
q:=a div 1000 mod 10;
b:=a div 100 mod 10;
s:=a div 10 mod 10;
g:=a mod 10;
2、冒泡排序(以升序为例)
for i:=1 to n-1 do
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; end;
3、求素数(标签法)
var
a,i:longint;
f:boolean;
begin
readln(a);
f:=true;
for i:=2 to trunc(sqrt(a)) do
if(a mod i=0) then f:=false;
if a=1 then f:=false;
if f=true then writeln('T') else writeln('F');
end.
4、字符图形(金字塔)
var
i,j,n:longint;
begin
readln(n);
for i:=1 to n do
begin
write('':n-i);
for j:=1 to 2*i-1 do write('*');
writeln;
end;
end.
5、闰年判断
四年一闰,百年不闰,四百年又闰。
(y mod 4=0)and(y mod 100<>0)or(y mod 400=0)
6、各类三角形的判别
a、b、c三边能构成三角形的条件:任意两边和大于第三边
(a+b>c)and(b+c>a)and(c+a>b)
a、b、c三边能构成直角三角形的条件:存在两边平方和等于第三边平方
(a*a+b*b=c*c)or(b*b+c*c=a*a)or(c*c+a*a=b*b)
a、b、c三边能构成锐角三角形的条件:任意两边平方和大于第三边平方
(a*a+b*b>c*c)and(b*b+c*c>a*a)and(c*c+a*a>b*b)
a、b、c三边能构成钝角三角形的条件:存在两边平方和小于第三边平方
(a*a+b*b<c*c)or(b*b+c*c<a*a)or(c*c+a*a<b*b)
7、完全数
a:array[1..5] of longint=(6,28,496,8128,33550336);
【第二层级 稍加思索】
1、最大公约数、最小公倍数
var
a,b,r:longint;
begin
readln(a,b);
while b>0 do
begin
r:=a mod b;
a:=b; b:=r;
end;
writeln(a);
end.
2、筛法求素数
var
i,j,n:longint;
prime:array[1..1000] of boolean;
begin
prime[1]:=FALSE;
for i:=1 to 1000 do prime[i]:=true;
for i:=2 to trunc(sqrt(1000)) do
if prime[i] then
for j:=2 to 1000 div i do prime[i*j]:=false;
end.
3、重要函数(内部函数)
数学函数odd sqrt trunc
字符函数ord chr
字符串函数length(s),copy(s,b,le),pos(s,c),val(s,n),str(n,s),insert(s1,s2,n),delete(s,b,len)
4、重要函数(内部函数)
(1)标签法求素数
(2)筛法求素数
(3)辗转相除法求GCD,LCM
【第三层级 奇思妙想】
1、快速排序
2、动态规划
3、搜索
4、高精度算法
EX01 字符图形生成
var i,j,n:longint; begin readln(n); for i:=1 to n do begin write('':n-i); for j:=i downto 2 do write(chr(64+j),' '); writeln('A'); end; end.
EX02数学黑洞
【题目描述】
任意一个4位自然数,将组成该数的各位数字重新排列,形成一个最大数和一个最小数,之后两数相减,其差仍为一个自然数.重复进行上述运算,你会发现一个神秘的数.请编程把过程打印出来.
输入
一行:一个四位数n
输出
若干行:每行为一个减法算式
样例输入
1234
样例输出
4321-1234=3087
8730-378=8352
8532-2358=6174
7641-1467=6174
var a:array[1..4] of longint; i,j,b,mx,mn,t:longint; begin readln(b); while b<>6174 do begin a[1]:=b div 1000 mod 10; a[2]:=b div 100 mod 10; a[3]:=b div 10 mod 10; a[4]:=b mod 10; for i:=1 to 3 do for j:=1 to 4-i do if(a[j]>a[j+1]) then begin t:=a[j];a[j]:=a[j+1];a[j+1]:=t; end; mx:=a[4]*1000+a[3]*100+a[2]*10+a[1]; mn:=a[1]*1000+a[2]*100+a[3]*10+a[4]; b:=mx-mn; writeln(mx,'-',mn,'=',b); end; writeln('7641-1467=6174'); end.
EX03英雄卡
【题目描述】
小李非常迷恋收集各种干脆面里面的英雄卡,为此他曾经连续一个月都只吃干脆面这一种零食,但是有些稀有英雄卡真的是太难收集到了。后来某商场搞了一次英雄卡兑换活动,只要你有三张编号连续的英雄卡,你就可以换任意编号的英雄卡。小李想知道他最多可以换到几张英雄卡(新换来的英雄卡不可以再次兑换)。
输入
第一行,共一个整数n,表示小李拥有的英雄卡数。
第二行,共n个空格隔开的数字ai,表示英雄卡的编号。
输出
输出仅有一行,共1个整数,表示小李最多可以换到的英雄卡。
样例输入
6
3 1 2 4 4 5
样例输出
1
uses math; var a:array[1..100000] of longint; i,b,n,x,mx,mn:longint; begin readln(n); for i:=1 to n do begin read(b); inc(a[b]); mx:=max(mx,b); end; for i:=1 to mx-2 do if(a[i]>0) then begin mn:=min(min(a[i],a[i+1]),a[i+2]); x:=x+mn; dec(a[i+1],mn); dec(a[i+2],mn); end; writeln(x); end. { 20 1 4 6 8 7 3 5 5 6 3 3 5 8 9 7 6 6 7 8 10 5 }
EX04 哈夫曼编码
【题目描述】
哈夫曼编码是一种编码方式,是可变字长编码的一种,由Huffman于1952年提出。该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫Huffman编码。简单地来说,就是出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的。
现在请你模拟这样的原则对给定的一个字符串进行字母统计。
输入
只有一行,是一个字符串,由小写英文字母组成,长度不超过255个字符。
输出
有若干行,每行有两部分组成:一个字母和该字母出现的频率,中间用一个空格分隔,并按频率高低排列,频率相同时则按字母的ASC码的先后顺序排列。
样例输入
soon
样例输出
o 2
n 1
s 1
var num:array['a'..'z'] of longint; c:char; s:string; i,j,k,n:longint; begin readln(s); for i:=1 to length(s) do inc(num[s[i]]); for i:=255 downto 1 do for c:='a' to 'z' do if num[c]=i then writeln(c,' ',i); end.
EX05 立方和
【题目描述】
现给出一个三位数,先对这个三位数的各位数字的立方求和,然后再对求出的和中的各位数字的立方求和,如此一直继续下去,判断最后能否得到一个不再变化的固定值。如能得到一个固定值,就求出这个固定值;如果不能,则输出提示信息“error”。另外请注意,在求解过程中,若某一次求和过程中得到的值超过三位数,则取该数的低三位继续往下运算……
例如,对于三位数111,则第一次计算应是1×1×1+1×1×1+1×1×1=3,第二次计算应是0×0×0+0×0×0+3×3×3=27,第三次计算应是0×0×0+2×2×2+7×7×7=351,第四次计算应是3×3×3+5×5×5+1×1×1=153,第五次计算应是1×1×1+5×5×5+3×3×3=153,与第四次计算的结果相同,这时可不再计算,输出固定值153。
亲爱的同学,请你也来计算一下。
输入
只有一行,是一个三位数。
输出
也只有一行,如能得到一个固定值,则输出这个固定值;如不能,则输出一个提示信息“error”。
样例输入
111
样例输出
153
输入样例2:
102
输出样例2:
error
var x,g,s,b,t:longint; v:array[0..10000]of boolean; begin read(x); while true do begin t:=x; //保存一遍,因为下面x会变 b:=x div 100; s:=x div 10 mod 10; g:=x mod 10; x:=(b*b*b+s*s*s+g*g*g) mod 1000; //如超过三位按三位计算 if x=t then begin writeln(x);halt;end; //与上一数相同刚输出 if v[x] then begin writeln('error');halt;end; //出现过这个数 v[x]:=true; //这个数出现过 end; end.
EX06 所有数字和为M的三位数
【题目描述】
找出数字之和为M的所有三位数
输入
一行,一个整数M,1<=M<25,不考虑无解的情况
输出
若干行,从小到大每行一个符合条件的数
样例输入
7
样例输出
106
115
124
133
142
151
160
205
214
223
232
241
250
304
313
322
331
340
403
412
421
430
502
511
520
601
610
700
var i,j,k,n:longint; begin readln(n); for i:=1 to 9 do for j:=0 to 9 do for k:=0 to 9 do if i+j+k=n then writeln(i,j,k); end.
EX07 所有数字和为M的三位数素数
【题目描述】
找出数字之和为M的所有三位数
输入
一行,一个整数M,1<=M<25,不考虑无解的情况
输出
若干行,从小到大每行一个符合条件的素数
样例输入
7
样例输出
151
223
241
313
331
421
601
var i,j,k,n:longint; function prime(a:longint):boolean; var i:longint; begin if a<2 then exit(false); for i:=2 to trunc(sqrt(a)) do if a mod i=0 then exit(false); exit(true); end; begin readln(n); for i:=1 to 9 do for j:=0 to 9 do for k:=0 to 9 do if (i+j+k=n) and prime(i*100+j*10+k) then writeln(i,j,k); end.
EX08 棋盘格数:求正、长方形个数
【题目描述】
设有一个N*M方格的棋盘。求出该棋盘中包含有多少个正方形、多少个长方形(不包括正方形)。
例如:当N=2,M=3时:
正方形的个数有8个:即边长为1的正方形6个;边长为2的正方形有2个。
长方形的个数有10个:即2*1的长方形有4个;1*2的长方形有3个;3*1的长方形有2个;3*2的长方形有1个。
输入
一行: 两个整数N,M , 1<=N<=100,1<=M<=100
输出
两行:
第一行表示正方形的个数
第二行表示长方形的个数
样例输入
2 3
样例输出
8
10
提示
数长方形包括正方形的方法:(长边上的线段数)*(宽边上的线段数)如上例(2+1)*(3+2+1)=18个;数正方形方法:长*宽+(长-1)*(宽-1)+...+(长或宽为1),如上例2*3+1*2=8个;不包括正方形的长方形为18-8=10个。
var a,b,z,c,x:longint; begin readln(a,b); x:=((a+1)*a*(b+1)*b) div 4; //四边形个数 z:=0; //正方形个数 while(a>0)and(b>0) do begin z:=z+a*b; dec(a); dec(b); end; writeln(z); writeln(x-z); end.
EX09 王小二切饼
【题目描述】
王小二自夸刀工不错,有人放一张大的剪饼在砧板上,问他:“饼不许离开砧板,切100刀最多能分成多少块?”
王小二想知道切n刀最多能分成几块,你能帮助他吗?
输入
一行:一个整数n 1<=n<=100
输出
一行:一个整数
样例输入
1
样例输出
2
提示
递推公式:f[n]=f[n-1]+n
【代码1】
var a:array[0..120] of longint; i,n:longint; begin a[0]:=1; for i:=1 to 100 do a[i]:=a[i-1]+i; readln(n); writeln(a[n]); end.
【代码2】
var n:longint; begin readln(n); writeln((n+1)*n div 2+1); end.
EX10 删数
【题目描述】
输入一个高精度的正整数N,去掉其中任意S个数字后剩下的数字按原左右次序组成一个新的正整数。编程对给定的N和S,寻找一种方案使剩下的数字组成的新数最小。
输出去掉数字后组成的新的正整数(N不超过240位),如果高位为0,则应去掉多余的零。输入的数据不需要判错。
输入
两行:
第一行:一个不超过200位的数N
第二行:删除和数字个数S,S<200
输出
一行:删除后的最小数
样例输入
343652
3
样例输出
332
提示
要在343652中删除3个数字,使剩下的数字最小。那么,我们第一个要删的是4,4正好处于数的下降趋势中,第二个仍然删除下降趋势的6,第三个删除5。这是一种贪心算法思想,所以本题称之为贪心删数。
var s:string; i,n,w,len:longint; begin readln(s); readln(n); len:=length(s); for i:=1 to n do begin w:=1; while (w<len)and(s[w]<=s[w+1]) do inc(w); delete(s,w,1); dec(len); end; writeln(s); end.
EX11 乘地铁(metro)
【题目描述】
现在宁波市已经开通地铁了,而恰好ZYH小朋友要出去玩,不喜欢挤公交的他自然也没钱做出租车,于是地铁是一个非常好的选择。
地铁的票价表可以看成一个n*n的二维表,有n行,每行n个数,第i行第j列表示从第i个站点到第j个站点的票价。现在ZYH小朋友要去m个地方,记为ai(1<=i<=m),并且他们一开始在a0号点,每次他们会从ai-1到ai,直至到达终点am。
现在ZYH小朋友想知道他需要多少钱来买地铁票。
输入
输入的第一行是两个用空格隔开的整数n(1<=n<=100),m(1<=m<=100)。
接下来是n行的票价表,每行n个整数bi,j,(0<=bi,j<=100)。
接下来的一行包含m+1个整数表示ai ,即是a0~am ,(1<=ai<=n)。
输出
输出一个数,表示最后需要的钱数。
样例输入
3 3
0 1 2
1 0 3
3 4 0
1 2 3 1
样例输出
7
var a:array[1..120,1..120] of longint; b:array[0..120] of longint; i,j,n,m,x:longint; begin readln(n,m); for i:=1 to n do for j:=1 to n do read(a[i,j]); for i:=0 to m do read(b[i]); x:=0; for i:=1 to m do x:=x+a[b[i-1],b[i]]; writeln(x); end.
EX12 分数线确定(line)
【题目描述】
在模拟考试结束后不久,所有考生的分数已经汇总完成,老师们开始估计某所大学的录取分数线。分数线的划定是一个复杂的过程,但是可以根据以往录取人数进行估计。
老师们的估计方法如下,先得到某所大学以往的录取人数,k人。那么总分在前k名的同学都可以进入这所大学,第k名同学的分数就被作为分数线。但是考试中往往有分数相同的人,若分数线上的人有多名,那么这些同学将同时被录取,录取人数可能超过k人。
现在校长想要知道某所学校的分数线,以及实际可以录取的人数。
输入
第一行两个整数n和k,分别表示参加考试的人数和以往录取人数k。
接下来n行,每行1个整数,表示每位同学的总分。
输出
一行,两个整数,第一个是录取分数线,第二个表示实际录取的人数。两个数之间用一个空格分开。
样例输入
6 3
721
612
603
658
598
612
样例输出
612 4
提示
【说明】
前3名分别为721,658,612,分数线划定为612,而612共有2人,那么一共可以录取4人
【数据范围】
对于50%的数据:1<=k<=n<=1000,每个人分数x的范围0<=x<=1000.
对于100%的数据:1<=k<=n<=100000。每个人分数x的范围0<=x<=100000000
【代码1 50分】
var a:array[1..100005] of longint; i,j,n,k,x,t:longint; begin readln(n,k); for i:=1 to n do readln(a[i]); for i:=1 to n-1 do 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; end; x:=a[k]; for i:=k+1 to n do if (a[i]=x)then inc(k) else break; writeln(x,' ',k); end.
【代码2 100分】
var a:array[1..100005] of longint; i,j,n,k,x,t:longint; procedure Qsort(l,r:longint); var mid,i,j,t:longint; begin i:=l; j:=r; mid:=a[(l+r) div 2]; repeat while a[i]<mid do inc(i); while a[j]>mid do dec(j); if i<=j then begin t:=a[i]; a[i]:=a[j]; a[j]:=t; inc(i); dec(j); end; until i>j; if i<r then Qsort(i,r); if l<j then Qsort(l,j); end; begin readln(n,k); for i:=1 to n do readln(a[i]); Qsort(1,n); x:=a[k]; for i:=k+1 to n do if (a[i]=x)then inc(k) else break; writeln(x,' ',k); end.
EX13 最大公约数与最小公倍数
【题目描述】
两个正整数的最大公约数是G,最小公倍数是L,它们的和最小是多少?
输入
两个不大于10000的正整数G和L,中间用单个空格隔开。数据保证L是G的倍数。
输出
一个正整数,即最小的和。
样例输入
14 280
样例输出
126
function GCD(a,b:longint):longint; var r:longint; begin while b>0 do begin r:=a mod b; a:=b; b:=r; end; exit(a); end; var G,L,c,i:longint; begin readln(G,L); c:=L div G; for i:=trunc(sqrt(c)) downto 1 do if (c mod i=0)and(GCD(i,c div i)=1)then begin writeln(G*(i+c div i)); break; end; end.