Bài giải tham khảo Đề thi Tin học trẻ tỉnh Kontum năm 2015 ■ Bài giải tham khảo Đề thi Tin học trẻ tỉnh Trà Vinh năm 2018 ■ 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 An Giang năm 2021 ■ Bài giải tham khảo Đề thi Tin học trẻ TP. Vinh năm 2019■ Bài giải tham khảo Đề thi Tin học trẻ TP. Vị Thanh năm 2019
Trang 1Đề thi Tin học trẻ tỉnh Kon Tum năm 2015
Khối Trung học Cơ sở Thời gian làm bài: 150 phút
Hướng giải quyết:
- Khi cắt lần 1, có thể cắt theo chiều đứng (Đ) hay chiều ngang (N) vì đều chia bánh ra làm 2 phần, nên chúng ta chọn chiều đứng, vết cắt là Đ1:
- Khi cắt lần 2, nếu cắt theo chiều đứng chúng ta chỉ được 3 phần, trong khi cắt theo chiều ngang (số phần tối đa được cắt là 2), sẽ chia bánh ra làm 4 phần, nên chúng ta chọn chiều ngang, vết cắt là N2:
Trang 2- Khi cắt lần 3, có thể cắt theo chiều đứng (Đ) hay chiều ngang (N) vì đều chia bánh ra làm 6 phần (số phần tối đa được cắt là 2), nên chúng ta chọn chiều đứng, vết cắt là Đ3:
- Khi cắt lần 4, nếu cắt theo chiều đứng chúng ta chỉ được 8 phần, trong khi cắt theo chiều ngang (số phần tối đa được cắt là 3) sẽ chia bánh ra làm 9 phần, nên chúng ta chọn chiều ngang, vết cắt là N4:
Từ đây, chúng ta thấy rằng muốn cắt bánh để được số phần nhiều nhất phải theo qui luật sau đây:
Trang 3- Từ đây chúng ta thấy có qui luật: Nếu số lần cắt k là số chẵn (2, 4, 6, 8), số phần tối đa sau khi cắt sẽ là số phần tối đa theo mỗi chiều bình phương (22=4, 32=9, 42=16, 52=25); nếu số lần cắt k là số lẻ (1, 3, 5, 7), số phần tối đa sau khi cắt sẽ là số phần tối đa theo mỗi chiều x (số phần tối đa theo mỗi chiều – 1) (2x1=2, 3x2=6, 4x3=12, 5x4=20)
- Ngoài ra, chúng ta có thể thấy rằng nếu k là số chẵn (2, 4, 6, 8), số phần tối đa theo 2 chiều sẽ là (k+2)/2: thí dụ như (2+2)/2=4, (4+2)/2=3, (6+2)/2=4, (8+2)/2=5 Nếu k là số
lẻ (1, 3, 5, 7), số phần tối đa theo 2 chiều sẽ là (k+3)/2: thí dụ như (1+3)/2=2, (3+3)/2=3, (5+3)/2=4, (7+3)/2=5
Cuối cùng chúng ta tìm được công thức cho kết quả:
If k mod 2=0 then Write(SQR((k+2) div 2)) // Số lần cắt là số chẵn
else Write(((k+3) div 2)*((k+3) div 2-1)); // Số lần cắt là số lẻ
Close(Output);
End
Trang 4Hướng giải quyết:
- Do giới hạn của a[i] là 108 nên chúng ta phải dùng sàng nguyên tố Eratosthen để giải
quyết bài toán TD: Với Input như trên thì số lớn nhất của dãy số là SLN_DaySo=17:
Dùng mảng SNT[1 SLN_DaySo] để đánh dấu các số nguyên tố Đầu tiên cho
toàn bộ mảng bằng 1, riêng SNT[1]=0 vì 1 không là số nguyên tố
Chạy vòng for i từ 2 đến căn bậc 2 của 17 (cắt bỏ số lẻ là 4), nếu SNT[i]=1 thì đánh dấu các bội số của i là 0 ta thu được kết quả:
i Bội của i, đánh dấu 0 Ghi chú
2 4, 6, 8, 10, 12, 14, 16 Các số này không là số nguyên tố
3 6, 9, 12, 15 Các số 6, 12 đã được đánh dấu 0 từ i=2
4 4, 8, 12, 16 Các số 4, 8, 12, 16 đã được đánh dấu 0
Cuối cùng, chỉ còn lại các số nguyên tố được đánh dấu 1 là 2, 3, 5, 7, 11, 13 và 17
Như vậy, nếu SNT[i]=1 thì i là số nguyên tố, ngược lại i không là số nguyên tố
- Cách tìm ước số chung lớn nhất của 2 số, Thí dụ : a=12 và b=18
a = a mod b = 12 mod 18 = 12, giữ nguyên b=18
Đổi giá trị a và b => a =18, b=12
a = a mod b = 18 mod 12 = 6, giữ nguyên b=12
Đổi giá trị a và b => a=12, b=6
a = a mod b = 12 mod 6 = 0, giữ nguyên b=6
Đổi giá trị a và b => a=6, b=0
Đến khi b=0 thì ngưng, kết quả chính là a=6
- Sau khi đọc vào dãy số, dùng 2 vòng for i:=1 to n-1 và for j:=i+1 to n để xét tất cả các cặp số a[i] và a[j], nếu USCLN của a[i] và a[j] là số nguyên tố (SNT[USCLN(a[i],
a[j])]=1) thì tăng biến đếm
Trang 5Lập trình như sau:
{$M 11000000} // Tăng cường bộ nhớ
Var n, i, j, Dem, SLN_DaySo: LongInt;
SNT :array [1 10000000] of byte; // i là số nguyên tố thì SNT[i]=1
a :array [1 107] of byte; // n<=100, nên khai báo dư một chút
{ -} Function USCLN(a, b: LongInt): LongInt;
Var
i,j :LongInt;
Begin
Fillchar(SNT,sizeof(SNT),1); SNT[1]:=0;
For i:=2 to Trunc(SQRT(N)) do
If SNT[i]=1 then begin // Tìm các bội số của i<=N và gán là 0
Assign(Input, 'NTo.Inp'); Reset(Input);
If SNT[USCLN(a[i], a[j])]=1 then Inc(Dem);
Assign(Output, 'NTo.Out'); ReWrite(Output);
WriteLn(Dem);
Close(Output);
End
Trang 6Hướng giải quyết:
- Xét dãy số trung bình 1 2 2 3 4, vì số 1 là trung bình cộng của chính nó (a[1]/1) nên dãy
- Vậy số thứ i sẽ là a[i] = i*b[i] – (i-1)*b[i-1]
- Tóm lại ta có: a[1]=b[1], a[i] = i*b[i] – (i-1)*b[i-1] với i=2 đến n
Trang 7Assign(Output, 'SumAvr.Out'); ReWrite(Output);
For i:=1 to n do Write(a[i], ' ');
Close(Output);
End
Hướng giải quyết:
- Số bút chì cần mua là 36, mua 5 tặng 1 sẽ nhận được 6 Lấy 36/6=6 lần mua, nhưng thực tế chỉ cần mua 5 chiếc bút chì mỗi lần với giá là 5 nên số tiền cần trả là 6*5*5=150
- Trường hợp số bút chì cần mua không chia hết cho 6, thí dụ như 38 thì số lần mua được
ưu đãi là 38 div 6 = 6 lần và số bút chì mua không được tặng thêm là 38 mod 6 = 2 Số tiền cần trả là 6*5*5 + 5*2 = 150 + 10 = 160
- Vậy với n là số bút chì cần mua, k là số bút chì mua sẽ được tặng thêm 1 và p là giá mỗi chiếc bút, chúng ta có công thức:
Số tiền trả = n div (k+1) * p * k + (n mod (k+1)) * p
= p * ( (n div(k+1) * k) + n mod (k+1) ) = 5 * (6*5 + 2) = 160
Assign(Output, 'SALE.Out'); ReWrite(Output);
Write( p * ( n div (k+1) * k + n mod (k+1) ) );
Close(Output);
End
Trang 8Đề thi Tin học trẻ tỉnh Trà Vinh năm 2018
Khối Trung học Cơ sở Thời gian làm bài: 120 phút
Hướng giải quyết:
- Trường hợp n=15:
Xét số xuất phát là 15 div 2 = 7 => 7+8=15 => ngưng (Cách 1)
Giảm số xuất phát 1 là 6 => 6+7=13, 6+7+8=21 > 15 => ngưng
Giảm số xuất phát 1 là 5 => 5+6=11, 5+6+7= 18 => ngưng
Giảm số xuất phát 1 là 4 => 4+5=9, 4+5+6=15 => ngưng (Cách 2)
Giảm số xuất phát 1 là 3 => 3+4=7, 3+4+5=12, 3+4+5+6=18 => ngưng
Giảm số xuất phát 1 là 2 => 2+3=5, …, 2+3+4+5=14, 2+3+4+5+6=20 =>
ngưng
Giảm số xuất phát 1 là 1 => 1+2=3, …, 1+2+3+4+5=15 => ngưng (Cách 3)
- Tóm lại, dùng vòng For i:=n div 2 downto 1, cộng dồn các số j từ i, i+1, i+2, … vào
biến tổng (Tong) trong khi Tong<n Nếu Tong=n thì đây là một cách phân tích n thành
tổng các số nguyên liên tiếp
Trang 10Hướng giải quyết:
- Dùng 2 vòng For i:=1 to n-1 (để có số phía sau) và For j:=i+1 to n để duyệt qua tất cả các cặp số a[i] và a[j] Nếu a[i]+a[j]=k thì xuất ra kết quả là vị trí I và j
Lập trình như sau:
Var a: array[1 100] of integer;
n, k, i, j: Integer; Co_KQ: Boolean;
If Co_KQ then Begin // Nếu có, xuất các kết quả
WriteLn('Vi tri 2 goi co tong bang ',k);
Trang 11Hướng giải quyết:
- Sử dụng hàm Copy(Chuổi, vị trí, số ký tự), TD: Copy(‘ABCD’, 2, 3)=’BCD’
- Viết hàm Xoay(Chuổi Ch, vị trí VT), thí dụ như chuổi ABCD:
Nếu VT=1, kết quả là chuổi ABCD => Copy(Ch,1,4)+ Copy(Ch,1,0)
Nếu VT=2, kết quả là chuổi BCDA => Copy(Ch,2,3)+ Copy(Ch,1,1)
Nếu VT=3, kết quả là chuổi CDAB => Copy(Ch,3,2)+ Copy(Ch,1,2)
Nếu VT=4, kết quả là chuổi DABC => Copy(Ch,4,1)+ Copy(Ch,1,3)
Do đó, kết quả của hàm là Ch_KQ=Copy(Ch,VT,Length(Ch)+1-VT)+ Copy(Ch,1,VT-1)
- Viết hàm Palin(Chuổi Ch) trả về True nếu Ch là chuổi Palindrom hay False nếu ngược lại, TD: Ch=’ABCBA’, ký tự 1 sẽ được so sánh với ký tự 5 (đều là A), ký tự 2 so sánh với ký tự 4 (đều là B) Số lần so sánh là Length(Ch) div 2=2 Ký tự thứ i sẽ được so sánh với ký tự thứ Length(Ch)+1-i Chỉ cần có một sự khác nhau thì hàm trả về False
Lập trình như sau:
Var Ch: String;
i: Integer; Co_KQ: Boolean;
{ -}
Trang 12Function Xoay(Ch: String; VT: Integer): String;
Var Ch_KQ: String; i: Integer;
Var i: Integer;
Begin
For i:=1 to Length(Ch) div 2 do
If Ch[i] <> Ch[Length(Ch)+1-i] then Exit(False);
Exit(True);
End;
{====================================================================} Begin
Assign(Input,'Palin.Inp');
Reset(Input);
ReadLn(Ch);
Close(Input);
Co_KQ:=False; // Cần chạy trước đoạn này để biết có kết quả hay không
For i:=1 to Length(Ch) do
If Palin(Xoay(Ch, i)) then Begin
Trang 13Đề thi Tin học trẻ tỉnh An Giang năm 2021
Khối Trung học Cơ sở Thời gian làm bài: 150 phút
Trang 14Hướng giải quyết:
- Việc đọc dữ liệu input khó hơn bình thường, cần phải phân tích:
- Truy vết tìm đường đi
Xác định vị trí của Max dòng 5: [5,2] => VT_Cot_Max=2
Trang 15Cho biến dòng d=n (5), biến cột c=VT_Cot_Max (2)
Tìm vị trí của số lớn nhất trong 2 số Q[d-1, c-1] và Q[d-1, c] (20 và 25) và xác định vị trí, chúng ta được kết quả:
Begin
Q[1,1]:=a[1,1];
For d:=2 to n do
For c:=1 to d do Begin
Max:=Q[d-1,c-1]; // Max của Ô trên, trái
If Max<Q[d-1,c] then Max:=Q[d-1,c]; // và ô trên
Q[d,c]:=Max+a[d,c]; // cộng với a[d,c] hiện tại
End;
End;
{ -} Procedure TruyVet;
Assign(Input, 'Bai01.Inp');
Reset(Input);
Trang 16Hướng giải quyết:
- Sử dụng mảng Chon[] để chọn các số từ dãy số 4 2 5 1 6 8 3, TD: Khi Chon={1, 0, 1, 0,
1, 1, 1} tương ứng với các số 4+2+5+6+8+3 = 26
- Mỗi vị trí VT sẽ có giá trị là 0 hay 1, xuất phát từ vị trí 1 (Try(1)) và kết thúc khi vị trí bằng n (If VT=n then _Print) là đã chọn được một bộ các số Nếu tổng của nó bằng S=26 thì in kết quả
- Khi Chon[VT]=1 thì số a[VT] được chọn, tổng sẽ cộng vào a[VT]
(Tong:=Tong+Chon[VT]*a[VT]) Gọi đệ quy Try(VT+1) để thử VT kế tiếp Khi quay lại thì trừ giá trị a[VT] ra khỏi tổng (Tong:=Tong-Chon[VT]*a[VT])
- Trong quá trình chọn tiếp tục các vị trí kế tiếp, nếu tổng vẫn còn <= S (Tong <= S) thì mới thử vị trí kế tiếp để loại bỏ các nhánh không có kết quả nếu đi tiếp các vị trí phía sau, giúp cho chương trình chạy nhanh hơn (If Tong <= S then Try(VT+1))
Trang 17Lập trình như sau:
Var n, i, S, Tong: Integer; Co_KQ: Boolean;
a, Chon: Array [1 33] of Integer;
{ -} Procedure _Print;
else If Tong<=S then Try(VT+1); // Thử ví trí kế VT+1 nếu tổng<=S
Tong:=Tong-a[VT]*Chon[VT]; // Trừ ra a[VT] nếu trước đó có chọn
End;
End;
{====================================================================} Begin
Trang 19Đề thi Tin học trẻ TP Vinh 2019
Khối Trung học Cơ sở Thời gian làm bài: 150 phút
Hướng giải quyết:
- Trong quá trình đọc file input ktra.inp, nếu đếm số phần tử bằng 0 vượt quá phân nửa
số phần tử của ma trận (=số dòng x số cột) => ma trận thưa hoặc số phần tử khác 0 bằng phân nửa số phần tử => không phải ma trận thưa thì ngưng đọc và kết luận tính
Trang 20If Dem_0>(sd*sc) / 2 then Write('Dung la ma tran thua')
else Write('Sai, khong la ma tran thua');
Close(Output);
End
Trang 21Hướng giải quyết:
- Đầu tiên, đọc file Input2.Int để lấy ra các từ gốc vào mảng Goc[] và các từ thay thế vào mảng The[]:
Dùng hàm Pos() để tìm vị trí của khoảng trắng ‘_‘ trong chuổi ‘ban_em’ => Pos=4
Từ gốc sẽ là chuổi con lấy từ vị trí 1 đến Pos()-1=3 => ‘ban’
Từ thay thế là chuổi con lấy từ vị trí Pos()+1=5 với độ dài là Length(‘ban_em’)
- Pos() = 6-4=2 => ‘em’
Biếm đếm (Dem) sẽ cho biết số từ cần thay thế (có 2 từ là ‘ban’ và ‘cao’)
- Tiếp tục đọc từng dòng của file Input1.int vào biến string Ch, dùng vòng For i chạy từ 1 đến Dem, nếu hàm Pos(Goc[i], Ch)>0 nghĩa là có từ Goc[i] trong dòng này, TD:
Ch=’chao cac ban’, Goc[1]=’ban’, => Pos()=10
Xóa Chuổi Ch tại vị trí Pos()=10, số ký tự cần xóa là Length(Goc[i])=3 =>
‘chao cac ‘
Chen chuổi thay thế The[i]=’em’ vào chuổi Ch tại vị trí Pos => ‘chao cac em’
Lập trình như sau:
Trang 22Var
Ch, Ch_Goc, Ch_The: String;
Goc, The: Array [1 55] of String;
For i:=1 to Dem do
If Pos(Goc[i], Ch)>0 then Begin
VT:=Pos(Goc[i], Ch); // Tìm vị trí từ ‘bạn’
Delete(Ch, VT, Length(Goc[i])); // Xóa từ ‘bạn’
Insert(The[i], Ch, VT); // Chen vào từ ‘em’
Trang 23Hướng giải quyết:
- Đầu tiên, viết Function NT(n: Integer): Boolean để xét số nguyên tố
- Chỉ cần dùng 2 vòng For x:=2 to n (do 2 là số nguyên tố nhỏ nhất) và For y:=x to n (do y>=x) để tìm bộ 3 số nguyên tố, vì tổng của 3 số là n nên số thứ ba sẽ là n-x-y và n-x-y>=y để tránh lặp lại các kết quả Nếu x và y và n-x-y là nguyên tố thì xuất kết quả
Lập trình như sau:
Var
n, x, y: Integer;
{ -} Function NT(n: Integer): Boolean;
Var i: Integer;
Begin
If n<2 then Exit(False); // Các số <2 không là số nguyên tố
For i:=2 to Trunc(SQRT(n)) do // Thử xem n có chia hết 2 căn(n)
If n mod i=0 then Exit(False); // Chia hết -> không là nguyên tố
Exit(True); // Không chia hết cho số nào -> nguyên tố
End;
{====================================================================} Begin
Trang 24Đề thi Tin học trẻ TP Vị Thanh 2019
Khối Trung học Cơ sở Thời gian làm bài: 150 phút
Hướng giải quyết:
- Đầu tiên, sắp thứ tự 3 số a1, a2, a3 tăng dần:
Nếu a1>a2: t=a1, a1=a2; a2=t;
Nếu a1>a3: t=a1, a1=a3; a3=t;
Nếu a2>a3: t=a2, a2=a3; a3=t;
Trang 25- Chúng ta thu được kết quả: a1=123, a2=234, a3=345
- Chuyển 3 giá trị thành chuổi Ch1=’123’, Ch2=’234’, Ch3=’345’
- Kết quả dãy không giảm sẽ là Ch1+Ch2, Ch1+Ch3, Ch2+Ch1, Ch2+Ch3, Ch3+Ch1, Ch3+Ch2 lần lượt là: ‘123234’, ‘123345’, 234123’, ‘234345’, ‘345123’, ‘345234’
If a1>a2 then Begin t:=a1; a1:=a2; a2:=t; End; // Sắp thứ tự tăng
If a1>a3 then Begin t:=a1; a1:=a3; a3:=t; End;
If a2>a3 then Begin t:=a2; a2:=a3; a3:=t; End;
Str(a1, Ch1); // Đổi số thành chuổi
Str(a2, Ch2);
Str(a3, Ch3);
WriteLn(Ch1+Ch2,' ',Ch1+Ch3,' ',Ch2+Ch1,' ',Ch2+Ch3,' ',Ch3+Ch1,' ', Ch3+Ch2);
// ReadLn;
End
Trang 26Hướng giải quyết:
- Tìm chuổi đảo của chuổi Ch=‘abcded’ => ChDao=‘dedcba’
- Lập bảng quy hoạch động Q[] để tìm chuổi con dài nhất của Ch và ChDao:
Dòng 0 bằng 0
Cột 0 bằng 0
Dòng 1 đến dòng n=Length(Ch)=6, với biến d là dòng và biến c là cột:
Nếu ChDao[d]=Ch[c] => Q[d, c]=Q[d-1, c-1]+1 (Q[ô trên, trái] + 1) Ngược lại, Q[d, c]=Max(Q[d, c-1], Q[d-1, c] (ô lớn nhất giữa ô trái và ô trên)
Trang 27Kết quả dãy con chung là ded
Begin
If a>b then Exit(a) else Exit(b);
End;
{ -} Procedure QHD;
Begin
For d:=0 to n do Q[d,0]:=0; // Cột 0 bằng 0
For c:=0 to n do Q[0,c]:=0; // Dòng 0 bằng 0
For d:=1 to n do
Trang 28For c:=1 to n do
If ChDao[d]=Ch[c] then Q[d,c]:=Q[d-1,c-1]+1 // [Ô trên, trái]+1
else Q[d,c]:=Max(Q[d,c-1], Q[d-1,c]); // Max(ô trái, ô trên)
End;
{ -} Procedure TruyVet;
While ChChen<>'' do Begin
While Ch[VT]=Ch[Length(Ch)+1-VT] do Inc(VT);
Insert(KyTuChen,Ch,Length(Ch)+2-VT) // Chen cuối chuổi
else If Ch[Length(Ch)+1-VT]=KyTuChen then
Insert(KyTuChen, Ch, VT); // Chen đầu chuổi
Inc(VT);
End;
WriteLn(Ch);
End;
Trang 29{====================================================================} Begin
Trang 30Hướng giải quyết:
- Nếu N mod A=0 thì kết quả chính là N, TD: N=120, A=8 => ‘120 chia het cho 8’
- Trường hợp N mod A<>0, chúng ta lấy N div A TD: N=123, A=8, 123 div 8=15, sau
đó lấy số này nhân với A, 15 x 8 = 120, chênh lệch là (123-120=3) Tuy nhiên với n=127
và A=8 thì cách làm này cho kết quả là 120 và chênh lệch là (127-120=7) Nhưng nếu chúng ta lấy số 128 cũng chia hết cho 8 nhưng chênh lệch là (128-127=1)
- Do đó chúng ta sẽ tạo ra 2 số cùng chia hết cho A là (N div A) * A và ((N div A)+1) *
A Số nào có chênh lệch với N nhỏ hơn sẽ được chọn để xuất kết quả
N1:=(N div A)*A; // Số nhỏ chia hết cho A
N2:=((N div A)+1)*A; // Số lớn chia hết cho A
Trang 31If abs(N-N1)<abs(N-N2) then Write(N1, ' chia het cho ', A) // Xuất N1
else Write(N2, ' chia het cho ', A); // Xuất N2
// ReadLn;
End
Hết tập 3
-ooOoo -