Giáo trình Olimpic lập trình
Trong Olimpic Tin học Mat-Xcơ-va, người ta ra cho học sinh phổ thông một số nhóm bài toán. Số
các bài toán dao động từ 5 đến 11 bài. Các bài toán luôn luôn có mức điểm khác nhau, xếp theo trật tự dễ
dần và khi tính điểm chỉ lấy 3 lời giải tốt nhất. Các thí sinh được báo trước tất cả những điều này. Những bài
đầu tiên có thể là khá khó, còn những bài cuối cùng mang tính chất khích lệ. Kỳ thi kéo dài 4 giờ, lời giải có
thể viết trên bất kỳ ngôn ngữ nào. Trước khi giải nhất thiết phải viết thuật giải bằng lời. Điều này làm cho
việc đọc chương trình dễ dàng. Tính rõ ràng của thuật toán, việc tiết kiệm số các thao tác, tính ngắn gọn của
chương trình được cho thêm điểm, còn việc lập trình sử dụng mảng thừa và có lỗi bị hạ thấp điểm.
Trong phát biểu các bài toán và trình bày thuật toán qui ước dùng các ký hiệu sau đây: Các mảng A1,
A
2,.An được ký hiệu là A[1:n] với A[i] là các phần tử của nó. Cũng như vậy kí hiệu A[1:m,1:n] và A[i,j]
cho mảng hai chiều.v.v.
Số lượng các phần tử của mảng và chỉ số các phần tử của mảng là các số tự nhiên, còn lại là các số
thực ( nghĩa là số với dấu phẩy động), nếu không có ước định nào khác.
Nếu ở đầu bài nói rằng “ Cho mảng A[1:n] thì học sinh cần viết chương trình tự nhập số n, tạo mảng
n phần tử và nhập giá trị của các phần tử này. Nếu trong ngôn ngữ ( Ví dụ ngôn ngữ Pascal.) không có
mảng động, thì cần chấp nhận n<100 và lập mảng 100 phần tử, nhưng chỉ nhập giá trị cho n phần tử cho
trước. Cũng như thế đối với mảng 2 chiều và nhiều chiều hơn. Tuy nhiên thí sinh được phép giả thiết phần
chương trình được viết là một phần của chương trình bao nó trong đó mảng đã được tạo lập và các phần tử
của mảng đã được nạp từ trước. Nhưng thí sinh cần nói rõ điều này. Tất cả các câu trả lời đều phải được đưa
ra màn hình hoặc máy in. Một lần nữa cần nhấn mạnh rằng lời giải phải là chương trình, không thể thay
chương trình bằng bất cứ lập luận nào.
Öt l¹i b¶ng A ta thªm b»ng c¸c sè 0. C¸c phÇn tö ®øng ë c¸c dßng vµ cét ®· ®−îc
®¸nh dÊu trong c¸c m¶ng B hoÆc C , tøc lµ :
If B[i]=1 or C[j]=1 then A[i,j]=0
Cã thÓ ®Ò xuÊt c¸ch gi¶i kh¸c chØ cÇn sö dông mét m¶ng phô C[1:n]. Trong c¸c tr−êng hîp ®ã m¶ng A sÏ
®−îc xÐt theo c¸c dßng. C¸c cét cã chøa c¸c phÇn tö 0 vÉn ®−îc ®¸nh dÊu trong m¶ng C nh− tr−íc, cßn cã
gÆp hay kh«ng sè 0 trong dßng ®ang xÐt ®−îc ®¸nh dÊu trong biÕn z, tøc lµ
If A[i,j]=0 then C[j]=1 ; z=1
Sau khi xem xÐt dßng i, nã sÏ ®−îc cho b»ng 0 nÕu z=1. Cuèi cïng xÐt m¶ng C vµ cho b»ng 0 c¸c cét j mµ
VIETBOOK
Trang 28
C[j]=1. Ch−¬ng tr×nh nµy ®−îc ®−a ra ë 88.5
C¸c lçi phæ biÕn khi gi¶i bµi nµy lµ :
1. 1. Xem xÐt m¶ng A, vµ nÕu phÇn tö A[i,j]=0 th× cho b»ng 0 hoÆc dßng i, hoÆc cét j, hoÆc c¶ hai c¸i ®ã. Khi
xem xÐt tiÕp tôc c¸c phÇn tö ®· ®−a vÒ b»ng 0 ®−îc coi lµ b»ng 0 tõ ®Çu vµ dÉn ®Õn c¸c b−íc ®−a vÒ 0 kh«ng
cÇn thiÕt.
2. Xem xÐt m¶ng A, vµ nÕu A[i,j]=0, th× ®−a j vµo phÇn tö C[k] tiÕp theo. Tõ ®ã cïng víi c¸c chØ sè j cã thÓ
®−îc ®−a ®i nhiÒu lÇn, vµ m¶ng C cã thÓ cÇn ®é dµi m*n tr¸i víi gi¶ thiÕt.
VIETBOOK
Trang 29
lêi gi¶i b»ng ng«n ng÷ pascal
olimpic 80.1.1
( In ra c¸c sè nguyªn tè nhá h¬n n)
program oli8011;
CONST
N=200;
LABEL
BR,LB;
VAR
m,i,,j,k,q : integer ;
p : array[1..n] of integer;
BEGIN
write('M:= ');
readln(m);
writeln(' Chuong trinh lay gia tri cua m= ',m);
if (m>=2) then
writeln(2);
if (m>=3) then writeln(3);
k:=1; p[k]:=3; i:=5;
while i<=m do
begin
for j:=1 to k do
begin
q:=p[j]
if (q*q>i) then goto br;
if (i mod q= 0) then goto np;
end;
if k=n then
begin
i:=m-1;
write(' Cac so con lai ');
writeln(' Khong the tinh toan chinh xac');
end
else
br: begin
writeln(i);
if (k<= n-1) then
VIETBOOK
Trang 30
begin
k:=k+1;
p[k]:=i ;
end;
end;
np: i:=i+2;
end;
readln;
END.
olimpic 80.1.2
(in ra cac so hoan vi)
PROGRAM OL8012;
CONST
mm=100;
VAR
m, i, j, k, n : integer;
a, p : array[1..mm] of integer;
BEGIN
write('m:=');
readln(m);
writeln(' chuong trinh nay lay gia tri m=',m);
for i:=1 to m do
begin
write('a[',i,']=');
readln(a[i]);
p[i]:= i;
end;
for i:=1 to m do write(a[i],' ');
writeln;
readln;
for i:=m-1 downto 1 do
if (p[i]<p{i+1]) then
begin
n:=p[i];
for j:=m downto i do
if (n<p[j]) then
begin
p[i]:= p[j];
p[j]:=n;
k:=1;
while i+k<m-k+1 do
VIETBOOK
Trang 31
begin
n:=p[i+k];
p{i+k]:=p[m+1-k];
p[m+1-k]:=n;
k:=k+1;
end;
j:=i;
end;
for i:=1 to m do write(a[p[i]],'');
writeln;
end;
readln;
END.
OLIMPIC 80.1.3
(n©ng bËc nhanh)
PROGRAM OLI8013;
VAR
a, b : real;
k, n : integer;
BEGIN
written(' a,k= '); readln(a,k);
write(a,' mu ',k,' = ');
b:=1;
while k>0 do
begin
n:=k div 2;
if (n+n<k) then
b:=b+a;
k:=n;
a:=a*a;
end;
writeln(b);
readln;
END.
olimpic 80.1.4
(nh÷ng phÐp tÝnh sè häc)
PROGRAM OL8014;
CONST
M=1;
VIETBOOK
Trang 32
N=9;
LABEL r;
var
i, j, k, y : integer;
a,b : array[1..n] of integer;
BEGIN
b[1]:=1;
k:=0;
a[2]:=0 ;
for i:=3 to n do
a[i]:=4;
r:
for i:=n downto 2 do
if a[i]=4 then
a[i]:=1
else
begin
a[i]:=a[i]+1;
y:=b[i-1];
case a[i] of
1 : b[i]:=y+i;
2 : b[i]:=y-i
3 : b[i]:=y*i;
4 : b[i]:=y div i;
end;
for j:=i+1 to n-1 do
b[j]:=b[j-1]+j;
if (b[n] m) then
goto r;
k:=k+1;
for j:=2 to n-1 do
write('(');
write('1');
for j:=2 to n do
begin
if (j>2) then
write(')');
case a[j] of
1: write('+');
2: write('-');
3: write('*');
4: write('%');
VIETBOOK
Trang 33
end;
write(j);
end;
writeln('=',m);
goto r;
end;
writeln(k);
readln;
END.
olimpic 80.2.1
{T×m kiÕm nh÷ng ph©n tö b»ng nhau}
PROGRAM OLI8021
LABEL
F;
VAR
i, j, p, q, b: integer;
a : array[1..2,1..15 ] of real;
ff : boolean;
BEGIN
for j:=1 to 15 do
begin
write('a[1,',j,']:=');readln(a[1,j]);
write('a[2,',j,']:=');readln(a[2,j]);
end;
ff:=false;
for i:=1 to 2 do
for j:=1 to 15 do
for p:=i to 2 do
begin
if i<p then
b:=1 else
b:=j+1;
for q:=p to 15 do
if (a[i,j]= a[p,q]) then
begin
ff:=true;
goto f;
end;
end;
VIETBOOK
Trang 34
F:
if ff then
writeln('a[',i,',',j,']=a[',p,',',q,']')
else
writeln('------');
END.
olimpic 80.2.2
(tæng c¸c b×nh ph−¬ng)
PROGRAM OLI8022;
VAR
m, i, j: integr;
ff :boolean;
BEGIN
write('m:=');
readln(m);
writeln('chuong trinh nay lay gia tri m=',m);
i:=1; ff:=true;
while (2*i*i<=m) and ff do
begin
j:= round(sqrt(m-i*i));
if (i*i+j*j=m) then
ff:=false else
i:=i+1;
end;
if ff then
write('net') else
writeln(i,'*',i,'+',j,'*',j,'=',m);
END.
OLIMPIC 80.2.3
( nh÷ng sè kh¸c nhau)
PROGRAM OLI8023;
CONST
n=100;
VAR
m, i, j, s: integer;
b : bolean
a : array[1..n] of integer;
BEGIN
write('m:=');
readln(m);
VIETBOOK
Trang 35
writeln(' Ch−¬ng tr×nh lÊy gi¸ trÞ m =',m);
for i:=1 to m do
begin
write('a[',i,']:=');
readln(a[i]);
end;
s:=0;
for i:=1 to m do
begin
b:=false; j:=i+1;
while(j<=m) and not b do
begin
b:=b or (a[i])= a[j]);
j:=j+1;
end;
if not b then
s:=s+1;
end;
writeln(s);
END.
OPLIMPIC 80.3.2
(M+1 TROng hÖ ®Õm c¬ sè hai)
PROGRAM OLI8032;
VAR
n, i, j: integer;
b : boolean ;
BEGIN
write('n:=');
readln(n);
b:=true;
for i:=1 to n do
begin
readln(j);
if b then
writeln(' ',1-j);
else
writeln(' ',j);
if j=0 then
b:= false
VIETBOOK
Trang 36
end;
if b then
writeln(' 1 ');
readln;
END.
OLIMPIC 80.3.3
(MAX cu¶ min)
PROGRAM OLI8033;
CONST
mm=10;
nn=20;
LABEL
si;
VAR
i, j, k, m, n: integer
x: : array[1..mm,1..nn] of integer;
min,max: integer;
BEGIN
write('m:=');
readln(m);
write('n:=');
readln(n);
for i:=1 to m do
for j:=1 to n do
begin
write('x[',i,',',j,']=');
readln(x[i,j]);
end;
for i:=1 to m do
begin
for
j:=1 to n do
begin
if (i>1) and (x[i,j ]<=max) then
goto si;
VIETBOOK
Trang 37
if (j=1) or (x[i,j]<=min) then
min:=x[i,j];
end;
max:=min;
k:=i;
si;
end;
writeln(k);
readln;
END.
OLIMPIC 80.3.4
(ho¸n vÞ c¸c sè 0, 1, 2)
PROGRAM OLI8034;
CONST
mm=100;
TYPE
el=0..2;
VAR
i,n: integer;
a: array[el] of 0..nn;
x: array[1..nn] of el;
BEGIN
write('n:='); readln(n);
writeln('Chuong trinh lay gia tri n=',n);
for i:=1 to n do
readln(x[i]);
writeln;
a[0]:=0; a[1]:=0; a[2]:=0;
for i:=1 to n do
a[x[i]]:=a[xi]]+1
for i:=1 to n do
if i<=a[0] then
x[i]:=0
else
if i<=n-a[2] then
x[i]:=1
else
x[i]:=2;
for i:=1 to n do
writeln(x[i]);
VIETBOOK
Trang 38
END.
OLIMPIC 81.1
(hµm sè)
PROGRAM OLI811;
VAR
n, i, j: integer;
BEGIN
write('n:='); readln(n);
writeln('Chuong trinh lay gia tri n=',n);
i:=1; j:=0;
while n>0 do
begin
if n mod 2=0 then
i:=i+j;
else
j:=j+i;
n:= n div 2;
end;
writeln(j);
END.
OLIMPIC 81.2
(béi bèn sè)
PROGRAM OLI812;
LABEL
BRJ,VSJO;
VAR
n, i, j, k, p:integer;
i1, j1, k1, p1: integer;
b: boolean;
begin
for n:=2 to maxint do
begin
b:=false;
for i:=1 to trunc(sqrt(n)) do
begin
for j:=1 to i do
begin
if
VIETBOOK
Trang 39
i*i+j*j>=n then
goto
brj;
for
k:=1 to j do
if
i*i+j*j+k*k<n then
begin
p:=trunc(sqrt(n-i*i-j*j-k*k));
if
(i*i+k*k+j*j+p*p=n) and (p<=k) then
begin
if (b) then
goto vsjo;
i1:=i; j1:=j; k1:=k; p1:=p;
b:=true;
end;
end;
end;
brj;
end;
end;
vsjo;
writeln(i*i+j*j+k*k+p*p,'=');
write(i,'*',i' + ',j,'*',j,' + ',k,'*',k,' + ',p,'*',p,' = ');
writeln(i1,'*',i1' + ',j1,'*',j1,' + ',k1,'*',k1,' + ',p1,'*',p1);
readln;
END.
PLIMPIC 81.3
{H×nh xo¸y tr«n èc}
PROGRAM OLI813;
CONST
NN=19;
VIETBOOK
Trang 40
VAR
i, j, k, n: integer;
a : array[1..nn,1..nn] of integer;
FUNCTION MOV: BOOLEAN ;
begin
mov:=false;
if k<=n*n then
begin
a[i,j]:=k;
k:=k+1;
mov:=true;
end;
end;
BEGIN
write('n:=');
readln(n);
k:=1; i:=1; j:=1;
repeat
while mov and (i+j<n+1) do j:=j+1; k:=k-1;
while mov and (i<j) do i:=i+1; k:=k-1;
while mov and (i+j>n+1) do j:=j-1; k:=k-1;
while mov and (i>j+1) do i=i-1; k:=k-1;
until k=n*n;
for i:=1 to n do
begin
for j:=1 to n do
writeln(a[i,j]:4);
readln;
end
END.
olimpic 81.4
{ c¸c sè lËp tõ c¸c ch÷ sè kh¸c nhau}
PROGRAM OLI814;
var
i, j, k, m: integer;
begin
for i:=1 to 9 do
for j:=0 to 9 do
if ij then
for
k:=0 to 9 do
VIETBOOK
Trang 41
if (ki) and (kj) then
for m:=0 to 9 do
if (mi) and (mj) and (mk) then
writeln(((i*10+j)*10+k*10)+m);
end.
olimpic 81.5
{lo¹t c¸c sè kh«ng}
PROGRAM OLI815;
const
nn=100;
var
n, i, t, max: integer;
a: array[1..nn] of real;
begin
write('N:='); readln(n);
for i:=1 to n do
begin
if a[i]0 then
begin
if (max<t) then max:=t;
t:=0;
end
else t:=t+1;
end;
if max<t then max:=t;
writeln;
writeln(max);
end.
OLIMPIC 82.1
{ h×nh ch÷ nhËt}
PROGRAM OLI821;
CONST
mm=100;
nn=100;
var
m, n, i, j, s: integer;
VIETBOOK
Trang 42
a : array[0..mm,0..nn] of byte;
begin
write(' M,N:=');readln(m,n);
for i:=0 to m do
for j:=0 to n do
if (i=0) or (j=0) then
a[i,j]:=0 else
begin
write('A[',i,',',j,']:=');
readln(a[i,j]);
end;
s:=0;
for i:=1 to m do
for j:=1 to n do
if (a[i,j]=1) and (a[i-1,j]+a[i,j-
1]=0) then
s:=s+1;
writeln(s);
END.
OLIMPIC 82.2
( SFile đính kèm:
Olympic tin hoc Moscow.pdf



