Bài giải tham khảo Đề thi Tin học trẻ tỉnh Lâm Đồng năm 2018 ■ Bài giải tham khảo Đề thi Tin học trẻ tỉnh Bắc Giang năm 2019 ■ Bài giải tham khảo Đề thi Tin học trẻ tỉnh Ninh Bình 2019 ■ Bài giải tham khảo Đề thi Tin học trẻ tỉnh Lâm Đồng năm 2019 ■ Bài giải tham khảo Đề thi Tin học trẻ huyện Vũ Quang năm 2019■ Bài giải tham khảo Đề thi Tin học trẻ tỉnh Gia Lai năm 2019
Trang 1Đề thi Tin học trẻ tỉnh Lâm Đồng năm 2018
Khối Trung học Cơ sở Thời gian làm bài: 150 phút
Hướng giải quyết:
- Dùng kỹ thuật tách số: Muốn tách số 234 thành số 2, 3 và 4 chúng ta thực hiện như sau:
2 3 mod 10 (phép chia lấy số dư, 234 / 10 =23 dư 4) = 4
23 4 div 10 (phép chia bỏ số lẻ: 234 / 10 =23.4, bỏ số lẻ thành 23) = 23
Thực hiện tiếp tục 2 thao tác trên chúng ta thu được thêm số 3 và số 2
- Sau khi tính tổng bình phương các chữ số của 234 (22 + 32 + 42 = 4 + 9 + 16 = 29) = 29,
ta xét nếu số 29 là số nguyên tố thì 234 là “số đẹp”
- Tạo hàm xét số k có phải là “số đẹp” hay không dựa theo kỹ thuật tách số như trên
- Tạo hàm xét số k có phải là số nguyên tố hay không:
Trang 2- Tạo biến số so xuất phát từ 11 (so <=10 chắc chắn không phải là số đẹp), biến đếm
dem xuất phát từ 0 Xét nếu so là “số đẹp” thì tăng biến dem đến khi nào = n thì ngưng
Lập trình như sau:
Var
n, Dem, So: LongInt;
{ -} Function NT(k: LongInt): Boolean;
Var i: LongInt;
Begin
If k<2 then Exit(False);
For i:=2 to Trunc(SQRT(k)) do
If k mod i=0 then Exit(False);
Exit(True);
End;
{ -} Function SoDep(k: LongInt): Boolean;
Var Tong_BP: LongInt;
While Dem<n do Begin
If SoDep(So) then Inc(Dem);
Trang 3Hướng giải quyết:
- Muốn số người đi thang máy là nhiều nhất thì phải chọn những người nhẹ nhất
- Sắp thứ tự mảng một chiều A chứa trọng lượng của những người cần đi thang máy tăng dần, chú ý lưu trữ thứ tự của những người này vào mảng TT khi nhập từ file input và giữ thứ tự này trong quá trình sắp xếp trọng lượng
- Chọn người sau khi đã sắp xếp theo trọng lượng trong khi tổng trọng lượng <= tải trọng của thang máy thì ngưng, đánh dấu vào mảng DD
- Duyệt lại mảng A, chỉ in ra các A[i] đã được đánh dấu trong mảng DD (DD[i]=True)
Lập trình như sau:
Var
a, b, TT: Array [1 20] of Integer; // Tối đa 20 người/ thang máy
DD: Array [1 20] of Boolean; // Mảng đánh dấu
While not EOF() do Begin
Read(a[i]); b[i]:=a[i]; // Lưu lại mảng A vào mảng B
TT[i]:=i; // Ghi thứ tự
Inc(i);
End;
Trang 4// Sắp thứ tự theo trọng lượng
For i:=1 to n-1 do
For j:=i+1 to n do
If a[i]>a[j] then Begin
t:=a[i]; a[i]:=a[j]; a[j]:=t;
t:=TT[i]; TT[i]:=TT[j]; TT[j]:=t; // Thứ tự cũng phải đảo theo
Trang 5Hướng giải quyết:
- Đánh dấu toàn bộ các ô là chưa duyệt (toàn bộ mảng đánh dấu DD có giá trị False)
- Dùng thuật toán vết dầu loang (đệ quy) để đi qua các ô có cùng giá trị 0 hay 1:
Trang 6 Nếu dòng >1 và ô trên (dòng hiện thời - 1) có cùng giá trị 0 hay 1 và ô trên chưa duyệt qua thì duyệt ô này
Nếu dòng <n và ô dưới (dòng hiện thời + 1) có cùng giá trị 0 hay 1 và ô dưới chưa duyệt qua thì duyệt ô này
Nếu cột >1 và ô trái (cột hiện thời - 1) có cùng giá trị 0 hay 1 và ô trái chưa duyệt qua thì duyệt ô này
Nếu cột < m và ô phải (cột hiện thời + 1) có cùng giá trị 0 hay 1 và ô phải chưa duyệt qua thì duyệt ô này
Lập trình như sau:
Var
n, m, i, j, x1, y1, x2, y2: Integer;
a: Array [1 100, 1 100] of Integer; // Đề thi không có giới hạn n,m
DD: Array [1 100, 1 100] of Boolean; // Mảng đánh dấu đã duyệt qua
CungMien: Boolean; // Cùng miền 0 hay miền 1 là True, ngược lại là False
{ -} Procedure Loang(d, c, v01: Integer); // Loang dòng, cột, giá trị ô 0 hay 1
Begin
DD[d, c]:=True;
If (d=x2) and (c=y2) then Begin CungMien:=True; Exit; End; // Ô đích
If (d>1) and (a[d-1,c]=v01) and (DD[d-1,c]=False) then Loang(d-1,c,v01);
If (d<n) and (a[d+1,c]=v01) and (DD[d+1,c]=False) then Loang(d+1,c,v01);
If (c>1) and (a[d,c-1]=v01) and (DD[d,c-1]=False) then Loang(d,c-1,v01);
If (c<m) and (a[d,c+1]=v01) and (DD[d,c+1]=False) then Loang(d,c+1,v01); End;
{====================================================================} Begin
While not EOF() do Begin
ReadLn(x1, y1, x2, y2);
FillChar(DD, sizeOf(DD), False);
CungMien:=False;
If a[x1, y1]=0 then Loang(x1, y1, 0)
else Loang(x1, y1, 1);
If CungMien then WriteLn(1) else WriteLn(2);
End;
Close(Input);
Close(Output);
End
Trang 7Đề thi Tin học trẻ tỉnh Bắc Giang năm 2019
Khối Trung học Cơ sở Thời gian làm bài: 120 phút
Hướng giải quyết:
- Tách nhóm 2 số: ví dụ số 30 25
Lấy mod 100 (chia 100 lấy số dư) để được 2 số cuối: 3025 mod 100 = 25
Div 100 (chia 100 lấy kết quả sau đó bỏ số lẻ): 3025 div 100 = 30
- Chạy vòng lặp For i:=1000 đến 9999 (mỗi số i có 4 chữ số)
Tách 2 số đầu sd và 2 số cuối sc
Nếu số i nào thỏa điều kiện i = (sd + sc)2 thì in số i vào file kết quả (có 3 số là
2025, 3025 và 9801
Trang 8Hướng giải quyết:
- Vì đề thi không nói nhập số phần tử n từ đâu nên chúng ta có thể nhập từ bàn phím
- Tạo n số ngẫu nhiên từ 0 đến 9 và ghi vào file RANDOM.INP
- Sắp thứ tự mảng A tăng dần
Trang 9- Đếm số phần tử = 0, số phần tử = 1,số phần tử = 2, …, số phần tử = 9:
Dùng vòng For i:=0 to 9
Biến đếm lấy giá trị 0
Dùng vòng For j:=1 to n, nếu số i cần đếm = phần tử a[j] thì tăng biến đếm
In kết quả ra file RANDOM.OUP
If a[i]>a[j] then Begin
t:=a[i]; a[i]:=a[j]; a[j]:=t;
End;
Assign(Output, 'RANDOM.OUP');
ReWrite(Output);
// In mảng dãy số ngẫu nhiên ra file
For i:=1 to n do Write(a[i], ' '); WriteLn;
// Đếm số lần xuất hiện của các số từ 0 đến 9 và in ra file
For i:=0 to 9 do Begin
Trang 10Hướng giải quyết:
- Xét số lớn là a trong hai số (nếu a < b thì hoán đổi giá trị của a và b), ghi các ước số của
số này vào mảng Uoc_a
- Xét số nhỏ hơn là b, nếu các ước số của a cũng là các ước số của b thì hai số là nguyên
tố tương đương; ngược lại thì không là số nguyên tố tương đương
Lập trình như sau:
Var
Uoc_a: Array [1 1000000] of LongInt;
SPT_a, t, a, b, Luu_a, i, Dem, SNTi: LongInt;
For i:=2 to Trunc(SQRT(k)) do
If k mod i=0 then Exit(False);
Exit(True);
End;
{ -} Function SNT(k: LongInt): LongInt;
Trang 11End;
Exit(i);
End;
{ -} Begin
If a=b then Begin Write(1); Close(Output); Exit; End;
If a<b then Begin t:=a; a:=b; b:=t; End;
For i:=1 to SPT_a do
If b mod Uoc_a[i]<>0 then Begin NTTD:=False; Break; End;
If NTTD then Write(1) else Write(0);
Close(Output);
End
(Xem tiếp bài 4 ở trang kế)
Trang 12Hướng giải quyết:
- Dùng hàm Pos(Chuổi con, Chuổi) để tìm vị trí của khóa k1 trong mật mã Nếu tìm được thì tăng biến đếm 1 (Dem_1) và thay thế các ký tự này bằng ký tự -
- Nếu Dem_1>1 và Dem_2>1
Nếu Dem_1=Dem_2 thì xuất k1+k2, ngược lại nếu k1>k2 thì xuất k1, còn không thì xuất k2
Ngược lại thì xuất „NULL‟
Trang 13If (Dem_1>1) and (Dem_2>1) then
If Dem_1=Dem_2 then Write(k1+k2)
Trang 14Đề thi Tin học trẻ tỉnh Ninh Bình năm 2019
Khối Trung học Cơ sở Thời gian làm bài: 120 phút
Hướng giải quyết:
- Tìm ước chung lớn nhất (UCLN) của 2 số a và b:
Nếu a=b thì UCLN=a hay b
Nếu a>b thì a:=a mod b, ngược lại b:=b mod a Thực hiện cho đến khi nào a mod b=0 hay b mod a=0 thì xuất ra số nhỏ trong 2 số
- TD: Tìm UCLN của 91 và 287
Do 91 < 287 nên chúng ta tiếp tục tìm UCLN của 91 và 287 mod 91 (=14),
nghĩa là tìm UCLN của 91 và 14
Trang 15 Do 91 > 14 nên chúng ta tiếp tục tìm UCLN của 91 mod 14 (=7) và 14, nghĩa là tìm UCLN của 7 và 14
Do 14 mod 7=0 nên chúng ta xuất ra số nhỏ là 7
- Tìm UCLN của 3 số a, b, c:
Đặt biến UC là UCLN của a và b
Tìm UCLN của UC và biến c
Begin
While (a mod b<>0) and (b mod a<>0) do Begin
If a>b then a:=a mod b;
If (a mod b=0) or (b mod a=0) then Break;
If b>a then b:=b mod a;
End;
If a=b then Exit(a);
If a>b then Exit(b) else Exit(a);
End;
{====================================================================} Begin
Trang 16Hướng giải quyết:
- Nếu chúng ta có 4 số a1, a2, a3, a4:
Lấy a1 so sánh với a2, a3, a4
Lấy a2 so sánh với a3, a4
Lấy a3 so sánh với a4
Nghĩa là chúng ta dùng hai vòng lệnh For như sau:
For i:=1 to n-1 do (chạy tới n-1 mới có số phía sau)
For j:=i+1 to n do … (i=1 thì j chạy từ 2 đến số cuối thứ 4 là các số phía sau, i=2 thì j chạy từ 3 đến số cuối thứ 4, …)
- Hai vòng For này chạy lần thứ 1 để đếm số cặp bằng nhau
- Chạy lần 2 hai vòng For này để xuất ra các cặp số bằng nhau
Trang 17If a[i]=a[j] then Begin
WriteLn('a',i,' = a',j,' = ',a[i]);
Trang 18Hướng giải quyết:
- Khi gặp input là chuổi, nên đọc nguyên chuổi vào rồi tách ra từng từ dựa theo khoảng trắng ' ' giữa hai từ
- Đánh dấu các từ chỉ chứa số như '108', '71', … bằng mảng boolean La_So (là số)
- Chỉ sắp thứ tự các từ i là số như trên (La_So[i] = True)
Đối từ thứ i là '108' sang dạng số So_i = 108
Đối từ thứ j là '71' sang dạng số So_j = 71
So sánh So_i và So_j để sắp xếp tăng dần
Trang 19Ch:=Ch+' '; // Nếu không thêm ' ' vào cuối chuổi, từ cuối sẽ bị mất
For i:=1 to Length(Ch) do
If Ch[i]=' ' then Begin // Khi duyệt hết một từ, tăng số từ, gán vào
Inc(So_Tu); // mảng a, xóa từ để tạo từ mới
For i:=1 to n do Begin
Val(a[i], So, Loi);
If Loi=0 then La_So[i]:=True;
End;
// Sắp thứ tự tăng dần
For i:=1 to n-1 do
For j:=i+1 to n do
If La_So[i] and La_So[j] then Begin // Chỉ sắp xếp các từ là số
Val(a[i], So_i, Loi); // Đổi thành số để so sánh, vì trong so
Val(a[j], So_j, Loi); // sánh chuổi, ‘108’ < ‘71’ do ‘1’ < ‘7’
If So_i>So_j then Begin
Tu:=a[i]; a[i]:=a[j]; a[j]:=Tu;
Trang 20Đề thi Tin học trẻ tỉnh Lâm Đồng năm 2019
Khối Trung học Cơ sở Thời gian làm bài: 150 phút
Hướng giải quyết:
Thay vì dùng 2 vòng For p:=1 to A và For q:=1 to B để tìm hai số p, q thỏa điều kiện
p+q=A và p*q=B thì chúng ta chỉ cần dùng một vòng For p:=1 to A-1 với q=A-p (chạy đến A-1 vì q>=1 và p+q=A)
Trang 21Hướng giải quyết:
- Dùng vòng For i:=1 to n để nối các chữ số của số i vào chuổi Ch Nếu n=11 thì
Ch=‟1234567891011‟
- Do n <501 nên dùng {$H+} để mở rộng độ dài của chuổi mới chứa đủ các chữ số trong trường hợp n có giá trị lớn
- Muốn cắt bỏ k=10 số của chuổi số Ch=‟1234567891011‟ thì dùng nguyên tắc sau:
Đi từ đầu đến ký tự kế cuối của chuổi ‟1 2 34567891011‟
Bắt đầu là số 1, nếu phía sau số 1 có số lớn hơn (số 2) thì xóa số 1 và tăng biến đếm (Dem=1) => „2 3 456789101 1‟
Tiếp tục là số 2, nếu phía sau số 2 có số lớn hơn (số 3) thì xóa số 2 và tăng biến đếm (Dem=2) => „3456789101 1‟
Nếu biến Dem=k thì ngưng
Khi chạy xong vòng For chuổi Ch=‟9111‟, nếu biến Dem (=9) vẫn còn < k (10)
Trang 22Lập trình như sau:
{$H+} // Sử dụng để có Ch chuổi dài hơn do số n < 501
Var
n, i, j, K, Dem, L: Integer; Ch, Ch_i: String;
Co_Lon_Hon: Boolean; // True nếu sau số hiện tại có số lớn hơn nó
// Xóa k số để thu được số lớn nhất
L:=Length(Ch); Dem:=0; i:=1;
While (i < L-1) and (Dem<k) do Begin
Co_Lon_Hon:=False;
For j:=i+1 to L do
If Ch[i]<Ch[j] then Begin Co_Lon_Hon:=True; Break; End;
If Co_Lon_Hon then Begin
Delete(Ch, i, 1); Dec(L); Inc(Dem); Dec(i);
End;
Inc(i);
End;
If Dem < K then Ch:=Copy(Ch,1,L-(K-Dem)); // Nếu xóa chưa đủ k thì
// xóa thêm các số cuối
Trang 23Hướng giải quyết:
- Dùng thuật toán Vết dầu loang (Loang) để đếm số cây liền nhau trên cùng hàng hay
cùng cột của mỗi phần tử a[i,j]
i, j-1 i, j i, j+1
Trang 24Var Dem_Doc, Dem_Ngang, Luu_d, Luu_c: Integer; // Đếm dọc, ngang, lưu dòng
Dem_Doc:=1; Luu_d:=d; // Lưu lại giá trị dòng hiện thời là d
While (d>1) and (a[d-1,c]=a[Luu_d,c]) do Begin Inc(Dem_Doc); Dec(d); End; d:=Luu_d;
While (d<m) and (a[d+1,c]=a[Luu_d,c]) do Begin Inc(Dem_Doc); Inc(d); End; d:=Luu_d;
Dem_Ngang:=1; Luu_c:=c; // Lưu lại giá trị cột hiện thời là c
While (c>1) and (a[d,c-1]=a[d,Luu_c]) do Begin Inc(Dem_Ngang); Dec(c); End; c:=Luu_c;
While (c<n) and (a[d,c+1]=a[d,Luu_c]) do Begin Inc(Dem_Ngang); Inc(c); End;
If Dem_Doc>=Dem_Ngang then Exit(Dem_Doc)
else Exit(Dem_Ngang);
End;
{===========================================================================} Begin
Trang 25Đề thi Tin học trẻ huyện Vũ Quang năm 2019
Khối Trung học Cơ sở Thời gian làm bài: 150 phút
Hướng giải quyết:
Trang 26- Tuy nhiên cách này sẽ chạy chậm khi n là số lớn (=109)
Lập trình theo cách thứ nhất như sau:
Trang 27Hướng giải quyết thứ hai:
- Cách thứ hai là thống kê số chữ số, lập công thức rồi tính số chữ số của số n
Từ 0 9 có 10 chữ số
Từ 10 99 có (99-10+1=90) số, mỗi số có 2 chữ số => có 90x2=180 chữ số Vậy từ 0 99 có 10+180=190 chữ số
Trang 28i:=1; LT10:=10; // Tìm đoạn xem n nằm trong đoạn nào 0 9, 0.99,
While n>LT10-1 do Begin LT10:=LT10*10; Inc(i); End;
Trang 29Hướng giải quyết:
- So sánh:
a[1] với a[2], a[3], … cho đến a[n]
a[2] với a[3], a[4], … cho đến a[n]
a[i] với a[i+1], a[i+2], … cho đến a[n]
a[n-1] với a[n]
- Dùng 2 vòng For:
Biến Boolean DonNhat=True (Đơn nhất)
For i:=1 to n-1
For j:=i+1 to n
Nếu a[i]=a[j] thì DonNhat=False và thoát vòng For
Nếu DonNhat thì xuất số 1, ngược lại xuất số 0
Trang 30Đề thi Tin học trẻ tỉnh Gia Lai năm 2019
Khối Trung học Cơ sở Thời gian làm bài: 150 phút
Hướng giải quyết:
- Có thể nhập số n từ bàn phím vì đề thi không nói đến file Input và Output
- Thay vì nhập biến n là số, có thể nhập biến n là chuổi (string) để dễ xử lý hơn và nhập
WriteLn('Ban hay nhap so n');
ReadLn(n); // Đọc số n theo dạng chuổi (String) để dễ xử lý
For i:=Length(n) downto 1 do
Write(n[i]);
End
Trang 31Hướng giải quyết:
- Nhập chuổi Ch=‟12/15‟
- Dùng hàm Pos để tìm vị trí vt của „/‟ (vt=3)
- Tử số là chuổi con từ vị trí đến vt-1 (1 đến 2)
- Mẫu số là chuổi con từ vị trí đến vt+1 đến cuối (4 đến 5)
- Đổi tử số và mẫu số sang dạng số bằng hàm Val(chuỗi, số, lỗi)
- Tìm ước số chung lớn nhất (UC) của tử số và mẫu số (=3) (bạn hãy tham khảo trang 14
và 15)
- Chia tử số và mẫu số cho UC
- Xuất kết quả (tử số, „/‟, mẫu số)
Begin
While (a mod b<>0) and (b mod a<>0) do Begin
If a>b then a:=a mod b;
If (a mod b=0) or (b mod a=0) then Break;
If b>a then b:=b mod a;
End;
If a=b then Exit(a);
If a>b then Exit(b) else Exit(a);
End;
{====================================================================} Begin
WriteLn('Ban hay nhap phan so');
Trang 32MS:=MS div UC;
WriteLn(TS, '/', MS);
End
Hướng giải quyết:
- Xuất phát với các biến i=1; độ dài L của chuổi (1234…) là 1 và tổng (Tong)=1
- Cho i tăng (-> 2, 3, 4…), biến i thành chuổi Dùng hàm Val để đổi từng chữ số của i thành số và cộng vào biến tổng, tăng giá trị của L lên 1
- Khi nào L=n là số chữ số cần tính tổng thì ngưng
For j:=1 to Length(Ch) do Begin
Val(Ch[j], So, Loi);
Trang 33Hướng giải quyết:
- Dùng 2 vòng For i chạy từ 1 đến m-1 và For j chạy từ 1 đến n-1 để duyệt từng phần tử a[i,j] của ma trận m x n
i+1, j i+1, j+1 m-1, n-1
Trang 34- Với mỗi phần tử a[i,j], hình vuông đồng nhất bậc 2 gồm các ô a[i,j], a[i+1,j], a[i, j+1] và a[i+1, j+1]
- Nếu 4 ô này bằng nhau thì tăng giá trị phần tử đếm (Dem[a[i,j]]) TD: a[i,j]=1 thì tăng giá trị Dem[1]
- Cuối cùng tìm giá trị lớn nhất Max của mảng Dem