100 đề Toán Tin Tin học & Nhà trường


(Dành cho học sinh Tiểu họcvà THCS)



tải về 1.1 Mb.
trang21/22
Chuyển đổi dữ liệu26.07.2016
Kích1.1 Mb.
#6336
1   ...   14   15   16   17   18   19   20   21   22

(Dành cho học sinh Tiểu họcvà THCS)


Hai số cuối là 59 và 65.

Giải thích: Chuỗi số được tạo ra từ việc cộng các số nguyên tố (ở hàng trên) với các số không phải là nguyên tố (hàng dưới), cụ thể như sau:


Bài 74/2001 - Hai hàng số kỳ ảo

(Dành cho học sinh THCS và PTTH)


Tổng các số từ 1 đến 2n: 1 + 2 + … + 2n = (2n*(2n+1))/2 = n*(2n+1).

Do đó, để hai hàng có tổng bằng nhau thì tổng của mỗi hàng phải là: (n*(2n+1))/2, như vậy n phải là số chẵn thì mới tồn tại hai hàng số kì ảo.

Tổng của n cột bằng nhau nên tổng của mỗi cột sẽ là: 2n+1.

ứng với một số A[i] (A[i] = 1, 2, …, 2n) chỉ tồn tại duy nhất một số B[i] = 2n -(A[i] -1) sao cho: A[i] + B[i] = 2n + 1;

Toàn bộ chương trình lời giải:

Program bai74;

uses crt;

var n:byte;

a:array[1..100]of 0..1;

th:array[0..50]of byte;

ok:boolean;

s:integer;

Procedure xet;

var i,j,tong:integer;

duoc:boolean;

Begin


tong:=0;

for j:=1 to n do tong:=tong+th[j];

if tong=s div 2 then

begin


duoc:=true;

for j:=1 to n-1 do

for i:=j+1 to n do

if th[j]+th[i]=(s div n) then duoc:=false;

if duoc then

begin


for i:=1 to n do write(th[i]:3);

writeln;


for i:=1 to n do write(((s div n)-th[i]):3);

ok:=true;

end;

end;


end;

Procedure try(i:byte);

var j:byte;

Begin


if i>n then xet

else if not ok then

for j:=th[i-1]+1 to 2*n do

begin


th[i]:=j;

try(i+1);

end;

End;


Procedure xuli;

var i:byte;

Begin

th[0]:=0;



ok:=false;

s:=n*(2*n)+1;

try(1);

if ok=false then write('Khong the sap xep');



End;

BEGIN


clrscr;

write('Nhap n:');readln(n);

if n mod 2 =1 then writeln('Khong the sap xep')

else xuli;

readln;

END.

(Lời giải của bạn Hoàng Phương Nhi - PTTH chuyên Lý Tự Trọng - Cần Thơ)



Nhận xét: Cách làm của bạn Hoàng Phương Nhi - PTTH chuyên Lý Tự Trọng - Cần Thơ dùng thuật toán duyệt nên chạy không được lớn. Với N = 20 thì chương trình chạy rất lâu, nếu N lớn hơn nữa thì không thể ra được kết quả. Bạn có thể cải tiến chương trình này bằng cách kiểm tra các điều kiện ngay trong quá trình duyệt để giảm bớt thời gian duyệt.

Cách làm khác dùng thuật toán chia kẹo chạy rất nhanh với N<35.

Tổng các số từ 1 đến 2n: 1 + 2 + .. + 2n = (2n*(2n+1))/2 = n*(2n+1).

Do đó, để hai hàng có tổng bằng nhau thì tổng của mỗi hàng phải là: (n*(2n+1))/2, như vậy n phải là số chẵn thì mới tồn tại hai hàng số kì ảo.

Tổng của n cột bằng nhau nên tổng của mỗi cột sẽ là: 2n+1.

ứng với một số A[i] (A[i] = 1, 2,.., 2n) chỉ tồn tại duy nhất một số B[i] = 2n -(A[i] -1) sao cho: A[i] + B[i] = 2n + 1

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+,Y+}

{$M 16384,0,655360}

uses crt;
const max =35;

fi = 'bai74.inp';

fo = 'bai74.out';
var d : array[0..max*(2*max+1) div 2] of byte;

tr : array[1..max,0..max*(2*max+1) div 2]of byte;

kq : array[1..max]of integer;

n,sum : integer;

ok : boolean;
procedure docf;

var f :text;

begin

ok:=false;



assign(f,fi);

reset(f);

read(f,n);

close(f);

end;
procedure lam;

var i,j :integer;

begin

sum:=n*(2*n+1) div 2;



fillchar(d,sizeof(d),0);

fillchar(tr,sizeof(tr),0);

d[0]:=1;

for i:=1 to n do

begin

for j:=sum-i downto 0 do



if d[j]=1 then

begin


d[j+i]:=2;

tr[i,j+i]:=1;

end;
for j:=sum-(2*n+1-i) downto 0 do

if d[j]=1 then

begin

d[j+2*n+1-i]:=2;



tr[i,j+2*n+1-i]:=2;

end;


for j:=0 to sum do

if d[j]>0 then dec(d[j]);

end;

ok:=(d[sum]=1);



end;
procedure ghif;

var f :text;

i,j :integer;

begin


assign(f,fo);

rewrite(f);

if ok=false then write(f,'No solution')

else


begin

i:=sum;j:=n;

while i>0 do

begin


if tr[j,i]=1 then kq[j]:=j else kq[j]:=2*n+1-j;

i:=i-kq[j];

dec(j);

end;


for j:=1 to n do write(f,kq[j]:6);

writeln(f);

for j:=1 to n do write(f,(2*n+1-kq[j]):6);

end;


close(f);

end;
BEGIN

docf;

if n mod 2=0 then lam;



ghif;

END.


Bài 75/2001 - Trò chơi Tích - Tắc vuông

(Dành cho học sinh THCS và PTTH)


(* Thuat toan:

Chia ban co lam 4 huong: Dong , Tay , Nam , Bac. Ta co cach di sau:

i) Luon di theo o lien canh voi o truoc

ii) Di theo huong khong bi chan. Vi du: o buoc 1 neu bi chan o huong Dong

thi di theo huong nguoc lai la huong Tay. Di theo huong Tay den khi huong Tay bi chan thi di theo huong Bac hoac Nam.

Trong khi di ta luon de y 2 dieu kien sau:

1. Neu co 3 o da lap thanh 3 dinh cua 1 hinh vuong ma o thu 4 chua bi di

thi ta se di o thu 4 va gianh duoc thang loi.

2. Neu co 2k+1(k>=1) o lien canh lien tiep thi kiem tra co the gianh thang

loi bang nuoc do^i khong? Nuoc do^i la nuoc ta danh vao 1 o nhung co the co duoc 2 hinh vuong. vi du: co 3 o (1,1);(1,2);(1,3) thi ta co the danh nuoc doi bang cach danh vao o (2,2) nhu vay ta co kha nang hinh thanh 2 o vuong. Nhung sau 1 nuoc di doi thi chi duy nhat chan duoc 1 o vuong, ta co the danh nuoc tiep theo de hinh thanh o vuong con lai va gianh duoc thang loi.

Bang cach danh nhu vay ban co the chien thang trong vong toi da la 10 nuoc.*)

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R+,S+,T-,V+,X+}

{$M 16384,0,655360}

CONST Min=-50;

Max=50;

TYPE Ma=Array[Min..Max,Min..Max] of char;



diem= Record

hg,cot:Integer;

End;

Qu=Array[1..Max] of diem;



VAR dmay,dng,dc1,dc2:diem;

hgdi:Integer; (*1:B ; 2:D ; -1:N ; -2:T*)

fin,ok:Boolean;

A:Ma;


Q,Qc:Qu;

dlt,dq,cq:Integer;

Procedure HienA(hgd,hgc,cotd,cotc:Integer);

Var i,j:Integer;

Begin

For i:=hgd to hgc do



Begin

For j:=cotd to cotc do Write(A[i,j],' ');

Writeln;

End;


End;

Procedure finish(d:diem);

Begin

A[d.hg,d.cot]:='x';



HienA(-10,10,-10,10);

Writeln('Ban da thua! An ENTER de ket thuc chuong trinh');

Readln;

Halt;


End;

Procedure Init;

Begin

Fillchar(A,sizeof(A),'.');



fin:=false;

Writeln('Gia thiet bang o vuong co: 101 hang (-50 -> 50)');

Writeln(' 101 cot (-50 -> 50)');

Writeln('Gia thiet may luon di nuoc dau tien tai o co toa do (0:0)');

dmay.hg:=0; dmay.cot:=0; A[dmay.hg,dmay.cot]:='X';

HienA(-10,10,-10,10);

dlt:=1;

End;


Procedure Sinh(d1:diem; Var d2:diem; hgdi,k:integer);

Var h,c:Integer;

Begin

h:=d1.hg; c:=d1.cot;



Case hgdi of

1: Dec(h,k);

2: Inc(c,k);

-1: Inc(h,k);

-2: Dec(c,k);

End;


d2.hg:=h; d2.cot:=c;

End;


Function kt(Var d1,d2:diem):boolean;

Var g1,g,g2:diem;

k,p:integer;

Begin


kt:=true;

k:=(dlt-1) div 2;

p:=2 div abs(hgdi);

sinh(dmay,g1,-hgdi,k);

sinh(dmay,g2,-hgdi,2*k);

sinh(g1,g,p,k);

sinh(dmay,d1,p,k);

sinh(g2,d2,p,k);

If (A[d1.hg,d1.cot]='.')and(A[g.hg,g.cot]='.')and(A[d2.hg,d2.cot]='.')then

begin A[g.hg,g.cot]:='x'; HienA(-10,10,-10,10); exit; end;

sinh(g1,g,-p,k);

sinh(dmay,d1,-p,k);

sinh(g2,d2,-p,k);

If (A[d1.hg,d1.cot]='.')and(A[g.hg,g.cot]='.')and(A[d2.hg,d2.cot]='.')then

begin A[g.hg,g.cot]:='x'; HienA(-10,10,-10,10); exit; end;

kt:=false;

End;

Procedure Ngdi;



Begin

Repeat


Write('Nhap toa do diem (hang,cot): '); Readln(dng.hg,dng.cot);

Until (dng.hg>=Min)and(dng.hg<=Max)and(dng.cot>=Min)and(dng.cot<=Max)and(A[dng.hg,dng.cot]='.');

A[dng.hg,dng.cot]:='1'; HienA(-10,10,-10,10);

End;


Function Hgchan:Integer;

Var Hgc:Integer;

Begin

If dmay.cot

Begin

Hgc:=2;


If Hgc=hgdi then Begin Hgchan:=Hgc; Exit; End;

End;


If dmay.cot>dng.cot then

Begin


Hgc:=-2;

If Hgc=hgdi then Begin Hgchan:=Hgc; Exit; End;

End;

If dmay.hg

Begin

Hgc:=-1;


If Hgc=hgdi then Begin Hgchan:=Hgc; Exit; End;

End;


If dmay.hg>dng.hg then

Begin


Hgc:=1;

If Hgc=hgdi then Begin Hgchan:=Hgc; Exit; End;

End;

Hgchan:=Hgc;



End;

Procedure Nap(Var Q:Qu; d1:diem; hgdi,k:Integer);

Var h,c:Integer;

d2:diem;


Begin

Sinh(d1,Q[cq],hgdi,k);

End;

Procedure Maydi;



Begin

Inc(dq);


if not ok then

Begin


If Q[dq].hgElse If Q[dq].hg>dmay.hg then hgdi:=-1

Else If Q[dq].cot

Else If Q[dq].cot>dmay.cot then hgdi:=2;

End;

dmay:=Q[dq];



A[q[dq].hg,q[dq].cot]:='x';

HienA(-10,10,-10,10)

End;

Procedure Process;



Var Hgc,p,i,ntt:Integer;

Begin


ok:=true; ntt:=0;

Ngdi;


Hgc:=Hgchan; Hgdi:=-Hgc;

Inc(cq); Nap(Q,dmay,hgdi,1); Maydi; Inc(dlt);

Repeat

Ngdi; Hgc:=Hgchan;



If ntt=1 then

If A[dc1.hg,dc1.cot]='.' then finish(dc1)

Else finish(dc2);

If ntt=0 then If (dlt>=3) and (kt(dc1,dc2)) then ntt:=1;

If (Hgc=Hgdi) then

If ok then

Begin

p:=2 div abs(Hgc);



For i:=1 to dlt-1 do

Begin


Inc(cq); Nap(Q,dmay,p,i); Nap(Qc,Q[cq],-hgdi,i);

Inc(cq); Nap(Q,dmay,-p,i);Nap(Qc,Q[cq],-hgdi,i);

End;

ok:=false;



dlt:=1;

End


Else

Begin


hgdi:=-hgdi; Inc(cq); Nap(Q,dmay,hgdi,dlt);

End;


If ntt=0 then

Begin


If dq=cq then Begin Inc(cq); Nap(Q,dmay,hgdi,1); End;

If A[Qc[dq].hg,Qc[dq].cot]='.' then finish(Qc[dq]);

Maydi; Inc(dlt);

End;


Until fin;

End;


BEGIN

Init;


Process;

END.
Bài 76/2001 - Đoạn thẳng và hình chữ nhật

(Dành cho học sinh PTTH)

Thuật toán:

- Xét đoạn thẳng cắt với từng cạnh của hình chữ nhật, điều kiện cắt của đoạn thẳng với một đoạn thẳng khác (cạnh của hình chữ nhật) là:

+ Hai đầu của đoạn thẳng khác phía với đoạn thẳng của hình chữ nhật;

+ Hai đầu của đoạn thẳng hình chữ nhật khác phía với đoạn thẳng.



Chương trình:

Program Bai76;

const inp= ‘input.txt’;

out= ‘output.txt’;

function cat (xs, ys, xe, ye, xl, yt, xr, yb: real): boolean;

var a, b, x, y: real;

lg1, lg2: boolean;

Begin


if xs=xe then

begin


lg1:=(xsxr) or ((ys>yt) and (ye>yt)) or ((yslg2:=(xs>xl) and (xsyb) and (ye>yb);

cat:=not (lg1 or lg2);

end


else begin

if ys=ye then

begin

lg1:=((xsxr) and (xe>xr)) or (ys>yt) or (ys

lg2:=(xs>xl) and (xe>xl) and (xsyb);

cat:=not (lg1 or lg2);

end

else begin



cat:=false;

a:=(ys-ye)/(xs-xe);

b:=ys-a*xs;

y:= a*xl+b;

if(y<=yt)and(y>=yb)then cat:= true;

y: =a*xr+b;

if(y<=yt)and(y>=yb)then cat:=true;

x:=(yt-b)/a;

if (x>=xl)and (x<=xr)then cat:=true;

x:=(yb-b)/a;

if (x>=xl)and (x<=xr)then cat:=true;

end;


end;

end;


procedure xuly;

var n, i: word; xs, ys, xe, ye, xl, yt, xr, yb: real;

fi, fo: text;

Begin


assign(fi, inp); reset (fi);

assign (fo, out); rewrite(fo);

readln(fi, n);

for i:=1 to n do begin

readln (fi, xs, ys, xe, ye, xl, yt, xr, yb);

if cat (xs, ys, xe, ye, xl, yt, xr, yb) then writeln (fo, ‘T’)

else writeln(fo, ‘F’);

end;


close (fi);

close (fo);

end;

BEGIN


xuly;

END.


(Lời giải của bạn Lê Mạnh Hà - Lớp 10A Tin - Khối PTCTT - ĐHKHTN - ĐHQG Hà Nội)
Bài 77/2001 - Xoá số trên bảng

(Dành cho học sinh Tiểu học)

1. Có thể thực hiện được.

Sau đây là một cách làm cụ thể: ta lần lượt xoá từng nhóm hai số một từ cuối lên: (23 - 22); (21 - 20); ....; (5 - 4); (3 - 2). Như vậy, sau 11 bước này trên bảng sẽ còn lại 12 số 1. Do đó, ta chỉ việc nhóm 12 số 1 này thành 6 nhóm có hiệu bằng 0. Khi đó, trên bảng sẽ chỉ còn lại toàn số 0.

2. Nếu thay 23 số bằng 25 số thì bài toán trên sẽ không thực hiện được.

Giải thích:

Ta có tổng các số từ 1 đến 25 = (1 + 25) x 25 : 2 sẽ là một số lẻ.

Giả sử, khi xoá đi hai số bất kỳ thì tổng các số trên bảng sẽ giảm đi là: (a + b) - (a - b) = 2b = một số chẵn.

Như vậy, sau một số bước xoá hai số bất kỳ thì tổng các số trên bảng vẫn còn lại là một số lẻ (số lẻ - số chẵn = số lẻ) và do đó trên bảng sẽ không phải là còn toàn số 0.



Bài 78/2001 - Cà rốt và những chú thỏ

(Dành cho học sinh Tiểu học)

Chú thỏ có thể ăn được nhiều nhất 120 củ cà rốt. Đường đi của chú thỏ như sau:

14->12->13->14->13->16->15->10->13

Do đó, số củ cà rốt chú thỏ ăn được khi đi theo đường này là:

14 + 12 + 13 + 14 + 13 + 16 + 15 + 10 + 13 = 120 (củ)

Bài 79/2001 - Về một ma trận số

(Dành cho học sinh THCS)

Bài này có rất nhiều nghiệm, để liệt kê tất cả các nghiệm thì phải sử dụng thuật toán duyệt. Do không gian tìm kiếm là cực kì lớn nên nếu duyệt tầm thường thì không thể giải đuợc, thậm chí còn không ra nghiệm nào cả. Vì vậy bài giải này duyệt bằng cách xây dựng một mảng ban đầu thoả mãn tích chất: dùng đúng 10 số 0, 10 số 1, ..., 10 số 9 và mỗi dòng không có quá 4 số khác nhau. Sau đó bằng cách hoán vị vòng các dòng để thoả mãn tính chất của đề bài.

Chọn mảng ban đầu như thế giảm đi rất nhiều khả năng và cũng làm mất đi rất nhiều nghiệm. Mảng ban đầu có thể có rất nhiều cách chọn, số nghiệm tìm ra phụ thuộc rất nhiều vào cách chọn này.

Ví dụ có thể chọn mảng ban đầu là:

(0,0,1,1,2,2,2,3,3,3)

(1,1,2,2,3,3,3,4,4,4)

(2,2,3,3,4,4,4,5,5,5)

(3,3,4,4,5,5,5,6,6,6)

(4,4,5,5,6,6,6,7,7,7)

(5,5,6,6,7,7,7,8,8,8)

(6,6,7,7,8,8,8,9,9,9)

(7,7,8,8,9,9,9,0,0,0)

(8,8,9,9,0,0,0,1,1,1)

(9,9,0,0,1,1,1,2,2,2)

Vì số nghiệm rất nhiều nên ta muốn ghi ra bao nhiêu nghiệm thì thay đổi biến sn để thay đổi số nghiệm cần ghi ra. Bài giải này in ra 100 nghiệm.

Các bạn chú ý rằng nếu có 1 bảng thoả mãn tính chất của bài thì tráo 2 dòng hoặc tráo 2 cột bất kì với nhau, hoặc quay 900 bảng ta có thể có các bảng cũng thoả mãn.

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+}

{$M 65384,0,655360}

uses crt;

type MG = array[1..10,1..10]of integer;

mg1c = array[1..10]of integer;


const N =10;

p = 4;


sn =100; {số nghiệm muốn ghi ra}

fo ='out.txt';

h :MG= {một cách chọn khác}

((0,0,0,1,1,1,2,2,2,3),

(1,1,1,2,2,2,3,3,3,4),

(2,2,2,3,3,3,4,4,4,5),

(3,3,3,4,4,4,5,5,5,6),

(4,4,4,5,5,5,6,6,6,7),

(5,5,5,6,6,6,7,7,7,8),

(6,6,6,7,7,7,8,8,8,9),

(7,7,7,8,8,8,9,9,9,0),

(8,8,8,9,9,9,0,0,0,1),

(9,9,9,0,0,0,1,1,1,2));
var a,dx : MG;

lap : mg1c;

dem : longint;

f : text;


procedure init;

var k :integer;

begin

dem:=0;


a:=h;

fillchar(dx,sizeof(dx),0);

fillchar(lap,sizeof(lap),0);

for k:=1 to N do lap[k]:=1;

for k:=1 to N do dx[k,a[1,k]+1]:=1;

end;
procedure ghikq(w:mg);

var i,j,ds:integer;

begin


inc(dem);

writeln('****** :',dem,':******');

writeln(f,'****** :',dem,':******');

for i:=1 to N do

begin

for j:=1 to N do



begin

write(w[i,j]:2);

write(f,w[i,j]:2);

end;


writeln;writeln(f);

end;


end;
function doi(k:integer):integer;

begin


if k mod N=0 then doi:=N

else doi:=k mod N;

end;
procedure try(k:byte;w:MG);

var i,j :byte;

luu :mg1c;

ldx :mg;


ok :boolean;

begin


luu:=lap;ldx:=dx;

for i:=1 to N do

begin

lap:=luu;dx:=ldx;



for j:=1 to N do w[k,j]:=a[k,doi(i+j-1)];
ok:=true;

for j:=1 to N do

begin

inc(lap[j],1-dx[j,w[k,j]+1]);



dx[j,w[k,j]+1]:=1;

if lap[j]>4 then

begin

ok:=false;



break;

end;


end;
if ok then

begin


if k=N then

ghikq(w)


else try(k+1,w);

end;


if dem=sn then exit;

end;


lap:=luu;dx:=ldx;

end;
BEGIN

clrscr;

init;


assign(f,fo);

rewrite(f);

try(2,a);

close(f);

END.

(Lời giải của Vũ Anh Quân)


Bài 80/2001 - Xếp số 1 trên lưới

(Dành cho học sinh THCS)

Bài toán có rất nhiều nghiệm, để liệt kê các nghiệm thì ta phải sử dụng thuật toán duyệt. Song duyệt thì rất lớn, mặt khác để ra được một cách điền thoả mãn thì không đơn giản chút nào (thời gian chạy sẽ rất lâu, thậm chí còn có thể bế tắc). Bài giải này duyệt theo một hướng tham lam có thể hiện ra được khá nhiều cách điền thoả mãn, tuy nhiên hướng giải này không hiện ra hết tất cả các nghiệm.

Hướng duyệt tham lam:

+ Mỗi dòng, mỗi cột có ít nhất một số 1.

+ Chia ma trận 10x10 thành 4 ma trận 5x5, mỗi ma trận 5x5 này sẽ được điền 4 số 1.

Cách kiểm tra tốt một ma trận sau khi điền có thoả mãn tính chất của bài không?

Duyệt cách chọn 5 hàng bất kì rồi xoá các số ở hàng đó, sau khi xoá xong ta tìm cách xoá 5 cột. Nếu sau khi xoá hàng xong mà cột nào còn số 1 thì phải xoá cột đó.

Nếu trong tất cả các cách xoá hàng, cột như vậy đều không xoá hết được thì bảng đó thoả mãn tính chất của bài.

Chương trình sau hiện ra 100 nghiệm.

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R-,S+,T-,V+,X+}

{$M 16384,0,655360}

uses crt;

const N =10;

p =16;


sn =100; {số nghiệm muốn hiện ra}

fo ='output.txt';

type MG =array[1..5,1..5] of byte;

var a : array[1..N,1..N] of integer;

w : array[1..600] of MG;

d : array[1..5] of integer;

c,dong,cc,ddd : array[0..N] of integer;

ok : boolean;

dem,sl : longint;

s : MG;


f : text;

procedure nap;

var i,j,k : integer;

begin


for i:=1 to 5 do

begin


k:=0;

inc(dem);

for j:=1 to 5 do

if i<>j then

begin

inc(k);


w[dem,j]:=s[k];

end;


end;

end;
procedure try(i:byte);

var j :byte;

begin


for j:=1 to 5 do

if d[j]=0 then

begin

s[i,j]:=1;



d[j]:=1;

if i=4 then nap

else try(i+1);

d[j]:=0;


s[i,j]:=0;

end;


end;

procedure kiemtra;

var i,j,use,k :integer;

begin


cc:=c;

for i:=1 to 5 do

for j:=1 to N do dec(cc[j],a[dong[i],j]);

use:=0;


for k:=1 to N do inc(use,ord(cc[k]>0));

if use<=5 then ok:=false;

end;

procedure thu(i:integer);



var j :integer;

begin


for j:=dong[i-1]+1 to N-5+i do

begin


dong[i]:=j;

if i=5 then kiemtra

else thu(i+1);

if ok=false then exit;

end;

end;


procedure lam;

var i,j,x,y,u,v,k :integer;

begin

for i:=1 to dem do



for j:=dem downto 1 do

for x:=1 to dem do

for y:=dem downto 1 do

begin


for u:=1 to 5 do

for v:=1 to 5 do a[u,v]:=w[i,u,v];

for u:=1 to 5 do

for v:=1 to 5 do a[u,5+v]:=w[j,u,v];

for u:=1 to 5 do

for v:=1 to 5 do a[5+u,v]:=w[x,u,v];

for u:=1 to 5 do

for v:=1 to 5 do a[5+u,5+v]:=w[y,u,v];


fillchar(c,sizeof(c),0);

fillchar(ddd,sizeof(ddd),0);

fillchar(dong,sizeof(dong),0);

for u:=1 to N do

for v:=1 to N do

begin


inc(c[v],a[u,v]);

inc(ddd[u],a[u,v]);

end;

ok:=true;



for k:=1 to N do

if (c[k]=0)or(ddd[k]=0) then ok:=false;

if ok then thu(1);

if ok then

begin

inc(sl);


writeln('*******:',sl,':*******');

writeln(f,'*******:',sl,':*******');

for u:=1 to N do

begin


for v:=1 to N do

begin


write(a[u,v],#32);

write(f,a[u,v],#32);

end;

writeln;writeln(f);



end;

if sn=sl then exit;

end;

end;


end;

BEGIN


clrscr;

fillchar(d,sizeof(d),0);

fillchar(w,sizeof(w),0);

fillchar(s,sizeof(s),0);

dem:=0;sl:=0;

try(1);


assign(f,fo);

rewrite(f);

lam;

close(f);



END.

(Lời giải của Đỗ Đức Đông)



Bài 81/2001 - Dãy nghịch thế

(Dành cho học sinh PTTH)

Program day_nghich_the;

uses crt;

const fn = 'nghich.inp';

gn = 'nghich.out';

nmax=10000;

var f,g:text;

n,i,j,dem:0..nmax;

a,b,luu:array[1..nmax] of 0..nmax;

procedure nhap;

begin


fillchar(a,sizeof(a),0); b:=a;

assign(f,fn); reset(f);

readln(f,n);

for i:=1 to n do read(f,a[i]); write(f);

for i:=1 to n do read(f,b[i]);

close(f);

end;

procedure tim_b;



begin

fillchar(luu,sizeof(luu),0);

for i:=1 to n do

begin


dem:=0;

for j:=i -1 downto 1 do

if a[i]

luu[a[i]]:=dem;

end;

for i:=1 to n do write(g,luu[i]:2);



writeln(g); writeln(g);

end;


procedure tim_a;

begin


fillchar(luu,sizeof(luu),0);

for i:=1 to n do

if b[i]>n-i then exit else

begin


j:=0;

dem:=0;


repeat

inc(dem);

if luu[dem]=0 then j:=j+1;

until j>b[i];

luu[dem]:=i;

end;


for i:=1 to n do write(g,luu[i]:2);

end;


BEGIN

nhap;


assign(g,gn);rewrite(g);

tim_b;


tim_a;

close(g);

END.

(Lời giải của bạn Lê Thị Thu Thuý - Lớp 11A2 PTTH chuyên Vĩnh Phúc - thị xã Vĩnh Yên - tỉnh Vĩnh Phúc)



Bài 82/2001 - Gặp gỡ

(Dành cho học sinh PTTH)

Bài này có thể giải dễ dàng nhờ nhận xét sau:

- Nếu k robot ở các vị trí mà tổng toạ độ của chúng (x+y) có tính chẵn lẻ khác nhau thì chúng không bao giờ gặp nhau (vì chúng luôn luôn di chuyển, không có robot đứng yên). Như vậy, sau khi loại trường hợp trên, gọi A[t, i j] là số bước di chuyển ít nhất để robot t di chuyển từ vị trí ban đầu đến ô (i, j). Khi đó, số bước di chuyển ít nhất mà k robot phải di chuyển để gặp nhau là:

Min (max(A(t, i j) với 1 <= t <= k, 1 <= i <= M, 1 <= j <= N. Loang ngược lại, ta có đường đi của những robot này.

Cài đặt chương trình:

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R-,S+,T-,V+,X+,Y+}

{$M 16384,0,655360}

Program MEET;

Uses crt;

Type point = record

x,y:integer;

End;


Const P:array[1..4,1..2] of integer=((0,1),(0,-1),(-1,0),(1,0));

Q:string='LRDU';

inp = 'MEET.INP';

out = 'MEET.OUT';

Var v: array[1..10] of point;

A: array[1..10,0..51,0..51] of integer;

B: array[0..51,0..51] of byte;

t: array[0..1,1..750] of point;

M,N,K,c,d,e,g,h,l,i,j,Min,Max:integer;

s,st:string;

f:text;

Procedure NoSolution;



Begin

Write(' # ');Readln;Halt;

End;

Procedure Input;



Begin

Assign(f,inp);Reset(f);

Readln(f,m,n,k);

If k>0 then

Begin

Readln(f,v[1].x,v[1].y);



e:=(v[1].x+v[1].y) mod 2;

End;


For c:=2 to k do

Begin


Read(f,v[c].x,v[c].y);

If (v[c].x+v[c].y) mod 2<>e then NoSolution;

End;

Fillchar(b,sizeof(b),1);



For c:=1 to m do

For d:=1 to n do read(f,B[c,d]);

Close(f);

End;


Procedure Solve;

Var Stop:boolean;

z:array[0..1] of integer;

Begin


For c:=0 to m+1 do

For d:=0 to n+1 do

If b[c,d]=0 then

For e:=1 to k do a[e,c,d]:=MaxInt else

For e:=1 to k do a[e,c,d]:=-1;

For c:=1 to k do

Begin

l:=1;g:=0;h:=1;z[0]:=1;z[1]:=0;



t[0,1]:=v[c];a[c,v[c].x,v[c].y]:=0;

Stop:=false;

While not Stop do

Begin


Stop:=true;

For d:=1 to z[g] do

For e:=1 to 4 do

Begin


i:=P[e,1]+t[g,d].x;

j:=P[e,2]+t[g,d].y;

If a[c,i,j]>l then

Begin


a[c,i,j]:=l;inc(z[h]);

t[h,z[h]].x:=i;

t[h,z[h]].y:=j;

Stop:=false;

End;

End;


l:=l+1;g:=1-g;h:=1-h;z[h]:=0;

End;


End;

Min:=MaxInt;

For c:=1 to m do

For d:=1 to n do

If b[c,d]<>1 then

Begin


max:=a[1,c,d];

For e:=2 to k do

If Max

If Min>Max then

Begin

Min:=Max;



i:=c;j:=d;

End;


End;

If Min=MaxInt then NoSolution;

Assign(f,out);Rewrite(f);

For e:=1 to k do

Begin

c:=i;d:=j;s:='';



While A[e,c,d]>0 do

Begin


l:=1;

While a[e,c+P[l,1],d+P[l,2]]+1<>a[e,c,d] do l:=l+1;

s:=Q[l]+s;

c:=c+P[l,1];d:=d+P[l,2];

End;

l:=l-1+2*(l mod 2);



st:=s[1]+Q[l];

For g:=1 to (min-a[e,i,j]) div 2 do s:=st+s;

Writeln(f,s);

End;


Close(f);

End;


BEGIN

Clrscr;


Input;

Solve;


Write('Complete - Open file ',out,' to view the result');

Readln


END.

(Lời giải của bạn Vũ Lê An - Lớp 12T2 - Lê Khiết - Quảng Ngãi)



Nhận xét: Bài làm của bạn Vũ Lê An phần kết quả còn thiếu trường hợp. Sau đây là một cách cài đặt khác song thuật toán cũng giống với Vũ Lê An.

Mở rộng bài toán: Cho một đồ thị gồm N đỉnh, có k con robot ở k đỉnh V1, V2,.., Vk. Sau mỗi đơn vị thời gian tất cả các con robot đều phải chuyển động sang các đỉnh kề với đỉnh nó đang đứng. Hãy tìm cách di chuyển các con robot để chúng gặp nhau tại một điểm.

a. Trong đồ thị vô hướng

b. Trong đồ thị có hướng (k = 2 - Đề thi chọn đội tuyển Quốc gia)
{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+}

{$M 65384,0,655360}

program Bai82_gap_go;{Author : Đỗ Đức Đông}

uses crt;

const max =50;

max_robot =10;

fi ='meet.inp';

fo ='meet.out';

tx :array[1..4]of integer=(0,-1,1,0);

ty :array[1..4]of integer=(-1,0,0,1);

h :string='LUDR';
var a :array[1..max,1..max]of byte;

robot :array[1..max_robot,1..2]of byte;

l :array[1..max,1..max,1..max_robot]of integer;

q :array[1..max*max,1..2]of byte;

dau,cuoi,m,n,r :integer;

best,mx,my :integer;

ok :boolean;
procedure docf;

var f :text;

k,i,j:integer;

begin


assign(f,fi);

reset(f);

readln(f,m,n,r);

for k:=1 to r do readln(f,robot[k,1],robot[k,2]);

for i:=1 to m do

for j:=1 to n do read(f,a[i,j]);

close(f);

end;
procedure loang(k:integer);

var x,y,s,u,v :integer;

begin


fillchar(q,sizeof(q),0);

dau:=1;cuoi:=1;

q[1,1]:=robot[k,1];

q[1,2]:=robot[k,2];

l[robot[k,1],robot[k,2],k]:=1;

while dau<=cuoi do

begin

x:=q[dau,1];y:=q[dau,2];



for s:=1 to 4 do

begin


u:=x+tx[s];

v:=y+ty[s];

if (u>0)and(v>0)and(u<=m)and(v<=n)and(a[u,v]=0)and(l[u,v,k]=0) then

begin


inc(cuoi);q[cuoi,1]:=u;q[cuoi,2]:=v;

l[u,v,k]:=l[x,y,k]+1;

end;

end;


inc(dau);

end;


end;
procedure lam;

var k,i,j :integer;

meet :boolean;

begin


fillchar(l,sizeof(l),0);

ok:=true;

for k:=2 to r do

if (robot[1,1]+robot[1,2]+robot[k,1]+robot[k,2]) mod 2=1 then ok:=false;


if ok then

begin


best:=maxint;

for k:=1 to r do loang(k);

for i:=1 to m do

for j:=1 to n do

begin

meet:=true;



for k:=1 to r do meet:=meet and (l[i,j,k]>0) and (l[i,j,k]if meet then

begin


best:=0;

for k:=1 to r do

if l[i,j,k]>best then

begin


best:=l[i,j,k];

mx:=i;my:=j;

end;

end;


end;

ok:=best

end;

end;
procedure ghif;



var f :text;

k,kk :byte;

lap :string;
procedure viet(x,y:byte);

var u,v,s :byte;

begin

for s:=1 to 4 do



begin

u:=x+tx[s];

v:=y+ty[s];

if (u>0)and(v>0)and(u<=m)and(v<=n)and(l[u,v,k]=l[x,y,k]-1) then

begin

if l[u,v,k]>1 then viet(u,v);



write(f,h[5-s]);

break;


end;

end;


end;
begin

assign(f,fo);

rewrite(f);

if ok=false then write(f,'#')

else

begin


for k:=1 to 4 do

if (mx+tx[k]>0)and(my+ty[k]>0)and(mx+tx[k]<=m)and(my+ty[k]<=n) then

if (a[mx+tx[k],my+ty[k]]=0) then kk:=k;

lap:=h[kk]+h[5-kk];


for k:=1 to r do

begin


if l[mx,my,k]>1 then viet(mx,my);

for kk:=1 to (best-l[mx,my,k]) div 2 do write(f,lap);

writeln(f);

end;


end;

close(f);

end;
BEGIN

docf;


lam;

ghif;


END.
Bài 83/2001 - Các đường tròn đồng tâm

(Dành cho học sinh Tiểu học)



Đáp số: Các số được điền như sau:


Bài 84/2001 - Cùng một tích

(Dành cho học sinh THCS và THPT)



Thuật toán: Gọi số lượng số xi =1 là a, số lượng số xi=-1 là b, số lượng số xi = 0 là c. Ta có: a+b+c=N.

Với mỗi giá trị c khác nhau ta có tương ứng một nghiệm. Nên số nghiệm bằng số giá trị mà c có thể nhận được. Nếu duyệt theo biến c thì có rất nhiều khả năng nên thay vì duyệt theo biến c ta duyệt theo a và b. Vai trò của các số bằng 1 và các số bằng -1 là như nhau nên ta có thể giả sử số lượng số bằng 1 lớn hơn số lượng bằng -1 (a>=b).

Vậy xi = a-b và xi2 = a+b (i = 1,..,N)

xixj = P (i =1, ..., N; j =1, ..., N; i<>j) suy ra P =2*xixj (i =1, ..., N -1; j =1, ..., N; i

Ta có phương trình: (a+b)+p=(a-b)2

suy ra 0 <= (a-b) <= sqrt(a+b+p) <= sqrt(N+p)<[sqrt(2*1010)] = 44721.

Vậy ứng với mỗi giá trị (a-b) ta có một giá trị (a+b) và một giá trị c. Lần lượt thử với từng giá trị của (a-b) rồi kiểm tra xem a, b và c thoả mãn các tính chất không?

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+,Y+}

{$M 16384,0,655360}

uses crt;

const fi ='input.txt';

fo ='output.txt';

var n,p, h :longint;

dem :longint;

t :real;

procedure docf;

var f :text;

begin


assign(f,fi);

reset(f);

read(f,n,p);

close(f);

dem:=0;

end;


procedure lam;

var can :longint;

begin

can:=trunc(sqrt(2*n));



for h:=0 to can do

begin


t:=h;

t:=sqr(t)-p;

if (t>=h)and(t<=n) then inc(dem);

end;


end;

procedure ghif;

var f :text;

begin


assign(f,fo);

rewrite(f);

writeln(f,dem);

close(f);

end;

BEGIN


docf;

if p mod 2=0 then lam;

ghif;

END.


(Lời giải của Đỗ Đức Đông)

Bài 85/2001 - Biến đổi 0 - 1

(Dành cho học sinh THPT)



Thuật toán: Bài này sử dụng thuật toán duyệt nhưng có một vài chú ý sau:

- Với 1 ô ta chỉ tác động nhiều nhất một lần.

- Thứ tự tác động là không quan trọng.

- Với một ô có nhiều nhất 5 ô ảnh hưởng được tới nó, vì vậy nếu với một ô ta biết 4 ô ảnh hưởng của nó có được tác động hay không thì ô còn lại ta sẽ biết là có nên tác động hay không tác động.

Từ các chú ý trên ta sẽ duyệt một dòng 1 (hoặc một cột 1) được tác động như thế nào khi đó các ô ở dòng 1 (hoặc cột 1) sẽ chỉ còn 1 ô ảnh hưởng tới nó. Ta sẽ biết được rằng các ô dòng 2 (hoặc cột 2) cũng sẽ được tác động như thế nào, cứ như vậy cho các dòng tiếp theo.

Bài sẽ phải duyệt 2N nếu duyệt theo dòng 1 (2M nếu duyệt theo cột 1) vì vậy để giảm độ phức tạp của bài bạn nên chọn duyệt theo chiều nào tuỳ thuộc vào M,N.

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R+,S+,T-,V+,X+}

{$M 16384,0,655360}

uses crt;

const max =100;

fi ='biendoi.inp';

fo ='biendoi.out';

tx : array[0..4]of integer=(0,0,-1,0,1);

ty: array[0..4]of integer=(0,-1,0,1,0);

type mg = array[1..max,1..max]of byte;

var a,b,td,lkq,c:mg;

m,n,dem,best:integer;

procedure docf;

var f :text;

i,j :byte;

begin

assign(f,fi);



reset(f);

readln(f,m,n);

for i:=1 to m do

for j:=1 to n do read(f,a[i,j]);

for i:=1 to m do

for j:=1 to n do read(f,b[i,j]);

close(f);

end;


procedure tacdong(i,j:byte);

var u,v,k :integer;

begin

for k:=0 to 4 do



begin

u:=i+tx[k];

v:=j+ty[k];

if (u>0)and(v>0)and(u<=m)and(v<=n) then a[u,v]:=1-a[u,v];

end;

inc(dem);



end;

procedure process;

var i,j,k :byte;

w : mg;


begin

c:=a;dem:=0;w:=td;

for i:=1 to n do

if td[1,i]=1 then tacdong(1,i);

for i:=2 to m do

for j:=1 to n do

if a[i-1,j]<>b[i-1,j] then

begin


tacdong(i,j);

td[i,j]:=1;

end;

for k:=1 to n do



if a[m,k]<>b[m,k] then begin a:=c;td:=w;exit;end;

if dem

begin

best:=dem;



lkq:=td;

end;


a:=c;td:=w;

end;


procedure try(i:byte);

var j :byte;

begin

for j:=0 to 1 do



begin

td[1,i]:=j;

if i=n then process

else try(i+1);

end;

end;


procedure ghif;

var f :text;

i,j :integer;

begin


assign(f,fo);

rewrite(f);

if best<>maxint then

begin


writeln(f,best);

for i:=1 to m do

for j:=1 to n do

if lkq[i,j]=1 then writeln(f,i,#32,j);

end

else writeln(f,'No solution');



close(f);

end;


begin

clrscr;


best:=maxint;

docf;


try(1);

ghif;


end.

(Lời giải của Đinh Quang Huy)



Bài 86/2001 - Dãy số tự nhiên logic

(Dành cho học sinh Tiểu học)

Số đầu và số cuối cần tìm của dãy số logic đã cho là: 10 và 24.

Giải thích: dãy số đó là dãy các số tự nhiên liên tiếp không nguyên tố.

Bài 87/2001 - Ghi các số trên bảng

(Dành cho học sinh THCS)

Procedure bai87;

uses crt;

var d, N:integer;

begin


clrscr;

write('Nhap so nguyen duong N: '); readln(N);

repeat

if N mod 2 = 0 then N:= div 2 else N:=N-1;



d:=d+1;

until N=0;

write('So lan ghi so len bảng: ', d);

readln;


End.

(Lời giải của bạn Cao Le Thang Long)


Bài 88/2001 - Về các số đặc biệt có 10 chữ số

(Dành cho học sinh THCS và THPT)



Thuật toán: mảng a[0..9] lưu kết quả, t[i] là số các chữ số i trong a. Theo bài ta có thể suy ra: a[0] + a[1] + ... + a[9] = số các chữ số 0 + số các chữ số 1 + ... + số các chữ số 9 = 10. Như vậy, ta dùng phép sinh đệ quy có nhánh cận để giải bài toán: ở mỗi bước sinh a[i], ta tính tổng các chữ số a[0]..a[i] (lưu vào biến s), nếu s >10 thì không sinh tiếp nữa. Sau đây là toàn bộ chương trình:

Procedure bai88;

const fo='bai88.out';

var a,t:array[0..9] of integer;

i,s:integer;

f:text;


procedure save;

var i:integer;

begin

for i:=0 to 9 do if a[i] <> t[i] then exit;



for i:=0 to 9 do write(f,a[i]); writeln(f);

end;


procedure try(i:integer);

var j:integer;

begin

for j:= 0 to 9 do



if ((i=j) and (t[j] +1 <=a[j]))) and (s<=10) then

begin


a[i]:=j;

inc(t[j]);

s:=s+j;

if i<9 then try(i+1) else save;



dec(t[j]);

s:=s-j;


end;

end;


BEGIN

assign(f,fo);rewrite(f);

for i:=1 to 9 do

begin


fillchar(t,sizeof(t),0);

s:=0;


a[0]:=i;

s:=s+i;


t[i]:=1;

try(1);


end;

close(f);

END.

(Lời giải của bạn Nguyễn Chí Thức - Lớp 11A1 khối PTCTT - ĐHSP Hà Nội)



Bài 89/2001 - Chữ số thứ N

(Dành cho học sinh THCS và THPT)



Thuật toán: từ nhận xét rằng có 9 số có 1 chữ số, 90 số có 2 chữ số, ... Ta sẽ xác định xem chữ số thứ N thuộc số có mấy chữ số và nó là số nào? Sau đó xem nó ở vị trí thứ mấy trong số đó.

Program bai89;

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+}

{$M 16384,0,655360}

Uses crt;

Const fi ='number.inp';

fo ='number.out';

cs:array[1..8] of longint = (9, 180, 2700, 36000, 450000, 5400000, 63000000, 720000000);

Var n : longint;

f,g :text;

Function num(n:longint):char;

var k, so, mu : longint;

s : string;

Begin


k:=1; mu:=1;

while (k<9)and(cs[k]

begin

n:=n-cs[k];



inc(k); mu:=mu*10;

end;


if mu=1 then so:=n div k

else so:=n div k+mu+ord(n mod k>0)-1;

str(so,s);s:=s[k]+s;

num:=s[n mod k+1];

End;

BEGIN


assign(f,fi); reset(f);

assign(g,fo); rewrite(g);

while not seekeof(f) do

begin


readln(f,n);

writeln(g,num(n));

end;

close(f);



close(g);

END.


(Lời giải của bạn Lê Văn Đức - Nguyễn Huệ - Hà Đông - Hà Tây)
Bài 90/2002 - Thay số trong bảng 9 ô

(Dành cho học sinh Tiểu học)

Do tổng các số trong các ô điền cùng chữ cái ban đầu là bằng nhau nên ta suy ra: 2M = 3I = 4S. Vì 4S chia hết cho 4, do đó 2M và 3I cũng chia hết cho 4.

Suy ra: I chia hết cho 4; M = 2S; 3I = 4S.

Đặt I = 4k (k = 1, 2,...), ta suy ra tương ứng: S = 3k, và M = 6k.

Ví dụ, với k = 1 ta có đáp số sau: I = 4, S = 3, M = 6;

Với k = 2, ta có: I = 8, S = 6, M = 12; ...
Bài 91/2002 - Các số lặp

(Dành cho học sinh THCS và THPT)

Program bai91;

{Thuat toan lua bo vao chuong}

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R+,S+,T-,V+,X+}

{$M 16384,0,655360}

USES crt;

CONST M1 = MaxInt div 4 + 1;

M2 = MaxInt;

fi = 'Bai91.Inp';

TYPE MA = Array[0..M1] of LongInt;

Var A: Array[0..3] of ^MA;

d,l :LongInt;

Procedure Init;

Var i:Byte;

Begin


For i:=0 to 3 do

begin


New(A[i]);

Fillchar(A[i]^,sizeof(A[i]^),0);

end;

End;


Procedure ReadF(k:ShortInt);

Var f:Text;

x:LongInt;

i,j:Integer;

Begin

Init;


Assign(f,fi);

Reset(f);

While Not SeekEof(f) do

begin


Read(f,x);

x:=x*k;


If x>=0 then

begin


i:=x div M1;

j:=x mod M1;

If i=4 then begin i:=3; j:=M1; end;

Inc(A[i]^[j]);

If A[i]^[j]>d then begin d:=A[i]^[j]; l:=x*k; end;

end;


end;

Close(f);

For i:=0 to 3 do Dispose(A[i]);

End;


BEGIN

Clrscr;


d:=0; l:=0;

ReadF(-1);

ReadF(1);

Writeln('So lap nhieu nhat la: ',l,#10#13,'Voi so lan lap : ',d);

Readln;

END.


(Lời giải của Nguyễn Toàn Thắng *)

Bài giải của bạn Nguyễn Toàn Thắng dùng thuật toán lùa bò vào chuồng. Sau đây là cách giải khác dùng thuật toán đếm số lần lặp.



Thuật toán: Tư tưởng thuật toán là dùng mảng đánh đấu có nghĩa là số x thì Lap[x] sẽ là số lần xuất hiện của số x trong mảng. Vì số phần tử của mảng nhỏ hơn hoặc bằng 106 nên phần tử của mảng Lap phải là kiểu dữ liệu để có thể lưu trữ được 106. Số x là số nguyên kiểu integer và do giới hạn bộ nhớ là 64K nên ta dùng ba mảng động như sau: MG = array[-maxint..maxint] of byte;

L[1..3] of ^MG;

Xử lý trong hệ cơ số 100.

Chương trình.

{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q+,R+,S+,T-,V+,X+,Y+}

{$M 16384,0,655360}

program bai91;{Đỗ Đức Đông}

uses crt;


const fi ='input.txt';

fo ='output.txt';

coso =100;
type mg =array[-maxint..maxint]of byte;
var L :array[1..3]of ^mg;

n,lap :longint;

kq :integer;

time :longint;

clock :longint absolute $00:$0046c;
procedure tao_test;

var f :text;

k :longint;

begin


n:=1000000;

assign(f,fi);

rewrite(f);

writeln(f,n);

for k:=1 to N do

if random(2)=1 then write(f,random(maxint),#32)

else write(f,-random(maxint),#32);

close(f);

end;
procedure danhdau(x:integer);

var i :integer;

begin

for i:=3 downto 1 do



if L[i]^[x]

begin


inc(L[i]^[x]);

break;


end

else L[i]^[x]:=0;

end;
procedure lam;

var f :text;

k :longint;

x :integer;

begin

for k:=1 to 3 do



begin

new(L[k]);

fillchar(L[k]^,sizeof(L[k]^),0);

end;


assign(f,fi);

reset(f);

read(f,n);

for k:=1 to n do

begin

read(f,x);



danhdau(x);

end;


close(f);
lap:=0;

for k:=-maxint to maxint do

if L[1]^[k]*sqr(coso)+L[2]^[k]*coso+L[3]^[k]>lap then

begin


lap:=L[1]^[k]*sqr(coso)+L[2]^[k]*coso+L[3]^[k];

kq:=k;


end;
for k:=1 to 3 do dispose(L[k]);

end;
procedure ghif;

var f :text;

begin


assign(f,fo);

rewrite(f);

write(f,kq);

writeln('So lan lap :',lap);

close(f);

end;
BEGIN

{tao_test;}

time:=clock;

lam;

ghif;


writeln((clock-time)/18.2:10:10);

END.
Bài 92/2002 - Dãy chia hết

(Dành cho học sinh THPT)

program DayChiaHet;

uses crt;

const inp='div.inp';

out='div.out';

var a:array[0..1] of set of byte;

g:text;

k,n,t,i,j,l:longint;



function f(x:longint):byte;

begin


x:=x mod k;

if x<0 then f:=x+k else f:=x;

end;

begin


clrscr;

assign(g,inp);reset(g);

readln(g,n,k);

t:=0;


read(g,j);

a[0]:=[f(j)];

for i:=2 to n do

begin


t:=1-t;

a[t]:=[];

read(g,j);

for l:=0 to k-1 do

if l in a[1-t] then

begin


a[t]:=a[t]+[f(l+j)];

a[t]:=a[t]+[f(l-j)];

end;

end;


close(g);

assign(g,out);rewrite(g);

if 0 in a[t] then write(g,1) else write(g,0);

close(g);

write('Complete - Open file ',out,' to view the result');

readln;


End.

(Lời giải của bạn Vũ Lê An - 12T2 - Lê Khiết - Quảng Ngãi)



Mở rộng bài toán:

1. Tìm dãy con liên tiếp có tổng bé nhất.

2. Tìm dãy con liên tiếp các phần tử thuộc dãy bằng nhau dài nhất.

3. Cho ma trận MxN hãy tìm hình chữ nhật có tổng lớn nhất (nhỏ nhất) với M,N<=100

4. Cho ma trận MxN hãy tìm hình chữ nhật có diện tích lớn nhất có các phần tử bằng nhau.

Cách giải bài toán 2 giải giống với bài toán 1, bài toán 3 và 4 giải giống nhau dựa trên cơ sở bài 1,2.



Cách giải bài toán 3: Xét hình các hình chữ nhật có toạ độ cột trái là i toạ độ cột phải là j (mất O(N2)). Coi mỗi dòng như một phần tử, để tìm hình chữ nhật có diện tích lớn nhất ta phải mất O(N) nữa. Như vậy độ phức tạp là O(N3).

Bài 93/2002 - Trò chơi bắn bi

(Dành cho học sinh Tiểu học)

Có 3 đường đi đạt số điểm lớn nhất là: 32.




tải về 1.1 Mb.

Chia sẻ với bạn bè của bạn:
1   ...   14   15   16   17   18   19   20   21   22




Cơ sở dữ liệu được bảo vệ bởi bản quyền ©hocday.com 2024
được sử dụng cho việc quản lý

    Quê hương