Tải bản đầy đủ (.doc) (22 trang)

Hướng dẫn học sinh sử dụng các phép toán DIV, MOD để rèn luyện kỹ năng lập trình

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (207.75 KB, 22 trang )

MỤC LỤC

Trang

1. Mở đầu………………………………………………………………………….1
1.1. Lý do chọn đề tài…………………………………………………………...1
1.2. Mục đich nghiên cứu……………………………………………………….1
1.3. Đối tượng nghiên cứu………………………………………………………1
1.4. Phương pháp nghiên cứu…………………………………………………...1
2. Nội dung sáng kiến kinh nghiệm……………………………………………...2
2.1. Cơ sở lí luận của sáng kiến kinh nghiệm…………………………………..2
2.2. Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm……………...2
2.3. Các giải pháp đã sử dụng để giải quyết vấn đề……………….....................3
2.3.1 Ôn tập về phép toán DIV, MOD…..…………….................................3
2.3.2 Lựa chọn một số bài toán cơ bản để vận dụng phép toán DIV,
MOD ...............................................................................................................
........5
2.3.3 Vận dụng làm một số bài tập từ các đề thi ……………………….......9
2.4. Hiệu quả của sáng kiến kinh nghiệm đối với hoạt động giáo dục, với bản
thân, đồng nghiệp và nhà trường.......…………………………………………..19
3. Kết luận, kiến nghị ...........................................................................................19


1. Mở đầu
1.1. Lý do chọn đề tài
Trong chương trình Tin học lớp 11, Ở bài 6 chỉ giới thiệu sơ qua về 2 phép toán
chia đối với số nguyên đó là DIV(chia lấy phần nguyên) và MOD(chia lấy phần dư)
và rất ít bài tập để học sinh vận dụng. Mặt khác 2 phép toán này và các định lý hoặc
bổ đề đi kèm thường dạy chủ yếu đối với các học sinh chuyên Tin còn với học sinh
THPT bình thường thì chỉ được giới thiệu sơ qua chủ yếu là để biết, và với một số
học sinh thì việc hiểu và sử dụng 2 phép toán này cũng rất trừu tượng, khó hiểu.


Tuy nhiên trong một số đề thi học sinh giỏi chúng ta thấy có rất nhiều bài tập đòi
hỏi phải sử dụng 2 phép toán này khi học sinh viết chương trình, ở các mức độ khác
nhau. Vì vậy, lượng kiến thức và thời lượng đó đó chưa đủ để học sinh có thể vận
dụng vào giải các bài tập liên quan, thường là các bài tập số học. Rèn luyện tư duy,
kỹ năng và tác phong lập trình là việc làm thường xuyên, có vai trò đặc biệt trong
khi bỗi dưỡng học sinh giỏi môn tin, hiệu quả của nó là động lực giúp học sinh
nắm vững kiến thức, phát triển tư duy, hình thành kỹ năng và kỹ xảo. Giúp học
sinh có khả năng thích ứng khi đứng trước một vấn đề cần giải quyết, hiểu được và
hiểu đúng vấn đề để từ đó có thể tìm được giải thuật phù hợp cho bài toán. Các bài
tập có sử dụng phép toán Div, Mod rất nhiều tuy nhiên giáo viên cần lựa chọn một
số bài tập phù hợp với khả năng tư duy của học sinh trường mình đang giảng dạy
để bồi dưỡng.
Vì lí do đó nên tôi chọn đề tài: “Hướng dẫn học sinh sử dụng các phép toán DIV,
MOD để rèn luyện kỹ năng lập trình” để nghiên cứu.
1.2. Mục đích nghiên cứu
Nghiên cứu một số vấn đề lý thuyết và thực tiễn việc sử dụng các phép toán
DIV, MOD để rèn luyện kỹ năng lập trình nhằm bồi dưỡng năng lực cũng như kỹ
năng lập trình, góp phần nâng cao chất lượng bồi dưỡng học sinh giỏi môn Tin học
ở trường trung học phổ thông Hoằng Hóa 3.
1.3. Đối tượng nghiên cứu
Đối tượng nghiên cứu: Việc sử dụng các phép toán DIV, MOD để rèn luyện kỹ
năng lập trình đối với môn tin học 11 của học sinh THPT.
Khách thể nghiên cứu: Học sinh thuộc đội tuyển học sinh giỏi môn Tin học của
trường THPT Hoằng Hóa 3
1.4. Phương pháp nghiên cứu
- Phương pháp nghiên cứu lý luận: Nghiên cứu các tài liệu, sách báo.
- Phương pháp điều tra thực tiễn: Quan sát việc học của học sinh trong quá trình
khai thác các bài tập sách giáo khoa, sách bài tập và các đề thi học sinh giỏi.
- Phương pháp thực nghiệm sư phạm


Trang

2


2. Nội dung sáng kiến kinh nghiệm
2.1. Cơ sở lí luận của sáng kiến kinh nghiệm
- Cơ sở tâm lý học:

+ Đặc điểm nhận thức của học sinh đối với môn Tin học:
Thực tế hiện nay đối với học sinh THPT phần lớn có thái độ xem bộ môn Tin
học là môn học phụ, ít quan tâm bởi vì học sinh bị tác động từ nhiều phía một cách
thụ động. Vì vậy việc tìm ra các học sinh có hứng thú và có một chút đam mê với
môn tin học là việc làm rất khó khăn đối với giáo viên khi chọn học sinh cho đội
tuyển học sinh giỏi của mình.
+ Tư duy của học sinh:

Khi làm bài tập phần này những em có kiến thức số học trong toán học tốt thì sẽ
hiểu đề bài nhanh, nhưng nhiều khi các em còn lúng túng, hiểu máy móc không
đúng bản chất cũng như yêu cầu của đề bài.
2.2. Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm
- Thực trạng công tác bồi dưỡng học sinh giỏi môn Tin học hiện nay.

Thực tế các học sinh tham gia đội tuyển đều có thể hiểu được ý nghĩa của 2 phép
toán này, xong việc vận dụng làm bài tập và rèn luyện kỹ năng thực hành còn rất
lúng túng bởi vì trong sách giáo khoa hay sách bài tập không có nhiều bài tập loại
này nhưng lại có trong đề thi học sinh giỏi những năm gần đây, và có một số bài
toán thực sự là khó với học sinh THPT không chuyên.
Qua những năm gần đây khi bồi dưỡng học sinh giỏi môn Tin học tôi nhận
thấy mảng kiến thức liên quan đến 2 phép toán DIV, MOD là loại bài tập khá thú

vị. Do đó tôi lựa chọn đề tài này để nghiên cứu và trình bày. Bởi việc giúp các em
hiểu được bản chất cũng như cách áp dụng 2 phép toán để tìm ra các cách giải cho
một số bài tập số học giúp các em rất tốt trong quá trình học và rèn luyện kỹ năng
lập trình.
- Những thuận lợi và khó khăn:

+ Thuận lợi:
- Công tác bồi dưỡng học sinh giỏi hiện nay đối với môn Tin học đã được nhà
trường quan tâm hơn, đặc biệt là đã có những phần thưởng có tính khích lệ đối với
giáo viên và học sinh hơn trước.
- Phong trào khuyến học, khuyến tài của huyện dành cho các học sinh đạt giải
trong các kỳ thi cũng là động lực thúc đẩy sự nổ lực của giáo viên và học sinh.
+ Khó khăn:

- Môn tin học ít có cơ hội chọn được học sinh tốt nhất ở các trường có chất
lượng đầu vào thấp.
- Phụ huynh không thích cho con em mình vào đội tuyển môn Tin học vì sợ
ảnh hưởng đến việc học và ôn thi Đại học. Học sinh ngày càng thực dụng hơn,
nhiều giáo viên chủ nhiệm thiếu tinh thần ủng hộ các em học sinh lớp mình vào đội
tuyển môn Tin học.
2.3. Các giải pháp đã sử dụng để giải quyết vấn đề
Trang

3


2.3.1 Ôn tập về phép toán DIV, MOD
Để ôn tập cách sử dụng phép toán div, mod cho học sinh tôi sử dụng bài toán cơ
bản sau:
Bài toán: Cho số tự nhiên N (N<=109), với N nhập từ bàn phím.Yêu cầu viết

chương trình:
a) Đếm số chữ số của N và thông báo kết quả ra màn hình;
b) Tính tổng các chữ số của N và thông báo kết quả ra màn hình;
c) Tìm chữ số đầu tiên của N và thông báo kết quả ra màn hình;
d) Tìm số đảo ngược các chữ số của N và thông báo kết quả ra màn hình.
Giáo viên có thể tách thành 4 bài toán riêng rẽ để ôn tập cũng được, tuy nhiên theo
tôi nên kết hợp 4 yêu cầu trong 1 chương trình để học sinh có sự tổng hợp, so sánh.
Nhắc lại hai phép toán cơ bản: DIV và MOD
- Chỉ áp dụng với kiểu dữ liệu số nguyên
- Phép toán DIV là phép chia lấy phần nguyên của số nguyên
- Phép toán MOD là phép chia lấy phần dư của số nguyên
Ví dụ: cho N=123456789
a := N mod 10; → Lấy chữ số tận cùng của N (tức a = 9)
N := N div 10; → Xóa bỏ chữ số tận cùng của N (N = 12345678, tức N giảm
10 lần)
Hướng dẫn thuật toán:
Câu a) Ban đầu khởi tạo biến đếm bằng 0; Lặp lại việc việc dùng phép toán DIV để
chia số N cho 10 đến khi nào thương bằng 0 thì dừng lại, mỗi lần thực hiện phép
chia (tức là N bớt đi một chữ số cuối) đồng thời tăng biến đếm lên 1 đơn vị. Vậy
biến đếm sẽ chứa kết quả là số lượng chữ số của số N. Ở câu này không cần sử
dụng phép toán MOD. Ở đây ta nên viết bằng lời để học sinh tự triển khai thuật
toán, nếu con vướng mắc thì giáo viên hướng dẫn, nếu học sinh yếu hơn thì ta có
thể viết tường minh hơn, ví dụ:
Ban dầu Dem=0;
Lặp lại:
N := N div 10;
Dem := dem+1;
Cho đến khi N =0;
Giáo viên có thể cho học sinh viết chương trình cho câu a trước sau đó bổ sung các
lệnh để hoàn thiện các câu còn lại.

Câu b) Sau khi làm xong câu a, giáo viên để học sinh tự làm câu b, trường hợp học
sinh còn lúng túng thì giáo viên mới hướng dẫn. Sau khi hoàn thiện câu b xong giáo
viên cũng cố lại thuật toán của câu b để học sinh mắm chắc thuật toán:
Ban đầu khởi tạo biến tổng bằng 0; Lặp lại việc việc dùng phép toán MOD để lấy
số dư của phép chia số N cho 10 (sodu :=N mod 10), phép toán DIV để chia số N
cho 10 (N := N div 10) đến khi nào thương bằng 0 thì dừng lại, mỗi lần thực hiện
Trang

4


phép chia (tức là N bớt đi một chữ số cuối) đồng thời ta cộng số dư đó vào biến
tổng. Vậy biến tổng sẽ chứa kết quả là tổng các chữ số của số N.
Câu c) Sau khi làm xong câu a, câu b giáo viên để học sinh tự làm câu c để kiểm tra
tư duy của các em, trường hợp học sinh còn lúng túng thì giáo viên lấy ví dụ hướng
dẫn, chẳng hạn với N =12345, sau khi thực hiện việc sodu := n mod 10 và n:= n div
10 liên tiếp, vậy đến khi N=0 thì biến sodu bằng bao nhiêu? Học sinh sẽ tìm được
câu trả lời. Sau khi hoàn thiện câu c xong giáo viên cũng cố lại thuật toán để học
sinh mắm chắc thuật toán:
Lặp lại việc việc dùng phép toán MOD để lấy số dư của phép chia số N cho 10
(sodu :=N mod 10), phép toán DIV để chia số N cho 10 (N := N div 10) đến khi
nào thương bằng 0 thì dừng lại. Vậy biến sodu (số dư cuối cùng) sẽ là chữ số đầu
tiên của số N.
Câu d) Đề làm câu d, giáo viên lấy một ví dụ cụ thể học sinh hướng dẫn quy luật để
tìm ra số đảo:
Ví dụ: N=12345; ban đầu sodao :=0;
Lần 1: sodu := n mod 10 =5, N := N div 10 = 1234; sodao = 5;
Lần 2: sodu := n mod 10 =4, N := N div 10 = 123; sodao = 5*?+4=54;
Lần 3: sodu := n mod 10 =3, N := N div 10 = 12; sodao = 54*?+3=543;
Lần 4: sodu := n mod 10 =2, N := N div 10 = 1; sodao = 543*?+2=5432;

Lần 5: sodu := n mod 10 =1, N := N div 10 = 0; sodao = 5432*?+1=54321;
Từ đó học sinh tìm ra quy luật như sau: sodao := sodao*10+sodu;
Sau khi bổ sung các lệnh để hoàn thiện câu d, giáo viên cũng cần nhắc lại thuật
toán để học sinh nắm chắc kiến thức:
Ban đầu khởi tạo biến sodao bằng 0; Lặp lại việc việc dùng phép toán MOD để lấy
số dư của phép chia số N cho 10 (sodu:=N mod 10), phép toán DIV để chia số N
cho 10 (N := N div 10) đến khi nào thương bằng 0 thì dừng lại, mỗi lần thực hiện
phép chia (tức là N bớt đi một chữ số cuối) đồng thời ta gán lại biến sodao bằng
sodao trước đó nhân 10 và cộng số dư đó vào. Vậy biến sodao sẽ chứa kết quả là số
đảo ngược của số N.
Nhận xét: (giáo viên nên đưa ra nhận xét để cũng cố kiến thức cho học sinh)
- Vòng lặp chính để giải quyết cả 4 câu trên là repeat ... until nên cả 4 câu chỉ cần
sử dụng chung 1 vòng lặp repeat ... until.
- Muốn sử dụng các chữ số của một số nguyên vào việc nào đó ta lặp lại việc
dùng phép toán DIV, MOD để chia số N cho 10 đến khi nào thương bằng 0 thì
dừng lại (tuy nhiên cũng phải căn cứ vào đề bài để xem lấy bao nhiêu chữ số để
tìm điều kiện dừng cho chính xác), trong quá trình đó ta có thể dùng các chữ số
của nó thông qua biến sodu để làm việc.
- Cần tránh trường hợp học sinh đi sai mục tiêu bởi vì làm bài này thì học sinh có
thể dùng các lệnh liên quan đến kiểu dữ liệu xâu để viết chương trình.
Chương trình tham khảo:
Trang

5


Program baicb1;
Var dem,N, tong, sodao,sodu: longint;
BEGIN
Write('Nhap N=');

Readln(N);
Dem:=0;
Tong:=0;
Sodao:=0;
Repeat
sodu := N mod 10;
Dem := Dem + 1;
Tong:= Tong + sodu;
Sodao := Sodao * 10 + sodu;
N:=N div 10;
Until N=0;
Writeln('So chu so = ' , Dem);
Writeln('Tong chu so = ' , Tong);
Writeln('Chu so dau tien = ' , sodu);
Writeln('So dao nguoc lai = ' , Sodao);
Readln;
END.
Yêucầu: Học sinh về nhà làm lại bài toán bằng cách chuyển từ câu lệnh repeat…
until sang câu lệnh while... do.
Từ bài toán trên ta đã ôn tập cho học sinh về việc sử dụng phép toán DIV,
MOD để đế đếm số chữ số của một số nguyên, tính tổng các chữ số, cách tìm số
đảo của một số nguyên, cách tìm chữ số đầu tiên của một số nguyên. Từ 4 kỹ năng
cơ bản đó ta cho học sinh làm các bài tập vận dụng ở mức độ 2 như sau:
2.3.2 Lựa chọn một số bài toán cơ bản để vận dụng phép toán DIV, MOD
Có nhiều bài tập liên quan, tuy nhiên ở đây tôi lựa chọn các bài tập sau đây:
Bài 1: Lập chương trình nhập từ bàn phím số nguyên N (0 < N <= 32767). Hãy xác
định và đưa ra màn hình số chữ 0 có nghĩa của N [1].
- Nhận xét: Với học sinh học khá môn toán đã biết chữ số có nghĩa là chữ số như
thế nào rồi nên ta chỉ cần hướng dẫn học sinh dùng phép toán DIV, MOD, học sinh
sẽ bắt chước cách sử dụng vòng lặp repeat ... until như bài trước để làm, kết hợp

thêm việc biện luận số dư. Có thể có học sinh lúng túng khi tìm điều kiện cho vòng
lặp, lúc đó giáo viên có thể lấy thêm ví dụ về chữ số có nghĩa, chẳng hạn:
Số 010 có 1 chữ số 0 có nghĩa, còn số 0 trước số 1 là chữ số 0 không có nghĩa, vậy
cần chia đến khi nào mà số đó còn lại mấy chữ số? Học sinh sẽ tự tìm được câu trả
lời và viết được chương trình.
Trang

6


Chương trình tham khảo:
program baivd1;
var n,du,d:longint;
begin
writeln('NHAP N ');
readln(n); d:=0;
repeat
du:=n mod 10;
if du=0 then inc(d);
n:=n div 10;
until n<10;
writeln('So chu so 0 co nghia la: ', d);
readln;
end.
Bài 2: Viết chương trình tìm và in ra màn hình các số đối xứng bé hơn hoặc bằng N
mà bình phương của nó cũng là một số đối xứng (1<=N<=10 7). Ví dụ số 11 là số
đối xứng có 112 = 121 cũng là số đối xứng [1].
Khi gặp bài này giáo viên nên để học sinh tự làm trước sau đó mới hướng dẫn lại
thuật toán để học sinh nắm vững thuật toán.
Hướng dẫn thuật toán: Gọi k là số cần tìm, ta dùng phép toán DIV, MOD để tìm số

đảo của số này để xem k có là số đối xứng không, nếu có thì đặt m=k*k sau đó lại
tạo số đảo của số này để xem m có là số đối xứng không, nếu có in ra kết quả.
Nhận xét: Khi làm bài này thì có học sinh sẽ vướng mắc về vấn đề kiểu dữ liệu để
chạy được hết giới hạn của đề bài vì vấn đề bình phương của một số, khi đó tùy vào
bài làm cụ thể của học sinh mà giáo viên hướng dẫn cho phù hợp.
Chương trình tham khảo:
program baivd2;
var n, k, du : longint;
m,s,t:QWord;
begin
writeln('Nhap N= '); readln(N);
for k:=1 to N do {kiem tra tung so k <=N xem co la so doi xung khong}
begin
s:=0; m:=k; {luu gia tri cua k vao bien m, goi s la so doi xung cua k}
while m>0 do
begin
du := m mod 10;
s:= s*10 + du;
m := m div 10;
end;
if s =k then
Trang

7


begin
{doan lenh kiem tra xem k*k co phai la sdx khong, tuong tu doan lenh tren}
s:=0; t:=k;m:=t*t;
{luu gia tri cua k*k bvao bien m, goi s la so doi xung cua k*k}

while m>0 do
begin
du := m mod 10;
s:= s*10 + du;
m := m div 10;
end;
if s =t*t then
begin
write(k, 'la so doi xung');
writeln('B.phuong cua ', k ,' la ', s, 'cung doi xung');
end;
end;
end;
readln;
end.
Bài 3: Viết chương trình liệt kê các số bé hơn hoặc bằng N (1<=N <=10 7) sao cho
số bình phương của số đó có phần bên phải trùng với chính số đó. Ví dụ số 25 khi
bình phương lên là 625 [1].
Khi gặp bài này giáo viên nên để học sinh tự làm trước sau đó mới hướng dẫn lại
thuật toán để học sinh nắm vững thuật toán. Và giống bài trước khi làm bài này thì
có học sinh sẽ vướng mắc về vấn đề kiểu dữ liệu để chạy được hết giới hạn của đề
bài vì vấn đề bình phương của một số, khi đó tùy vào bài làm cụ thể của học sinh
mà giáo viên hướng dẫn cho phù hợp.
Hướng dẫn thuật toán: Gọi k là số cần tìm, m=k*k là bình phương của số k, do k <
m nên ta dùng phép toán DIV, MOD theo k để kiểm tra xem các số dư của k và m
có bằng nhau hay không, ban đầu giả sử là bằng nhau ta dùng biến kiểm tra để đánh
dấu là true, trong quá trình kiểm tra nếu khác nhau thì đánh dấu lại biến kiểm tra là
false, quá trình đó lặp lại cho đến khi k div 10 = 0 trước, Nếu xong quá trình đó mà
biến kiểm tra vẫn bằng true thì in ra kết quả.
Chương trình tham khảo:

program bai3vd;
var n,k, du1, du2 :longint;
i, t, m: QWord;
kt :boolean;
begin
writeln('nhap n='); readln(n);
Trang

8


for k:=1 to N do
begin
i:=k;t:=k;
kt :=true; {gia su kiem tra la dung}
m :=i*i; {ktra so bphuong cua so i co phan ben phai trung voi i khong}
while (i>0) and kt do
begin
du1:= m mod 10;
du2 := i mod 10;
if du1 <> du2 then kt:=false; {ktra thay khong thoa man}
m:= m div 10;
i := i div 10;
end;
if (i=0) and kt then
begin
write(k, ' '); writeln(t*t);
end;
end;
readln;

END.
Bài 4: Viết chương trình nhập vào từ bàn phím số nguyên N (1<= N <= 1018).
In ra màn hình số nguyên nhận được từ N sau khi đã bỏ bớt đi các chữ số 0 và 5
trong số nguyên N [1].
Khi gặp bài này giáo viên nên lấy một ví dụ minh họa về yêu cầu của đề bài, ví dụ:
Với N=19002552 vậy sau khi bỏ số 0 và số 5 ta thu được số 1922, từ đó học sinh
xác định được yêu cầu, tìm thuật toán để để viết chương trình, sau đó nếu học sinh
còn vướng mắc thì giáo viên mới hướng dẫn lại thuật toán.
Hướng dẫn thuật toán: Yêu cầu học sinh sử dụng phép toán div, mod và nhân
ngược lại theo hệ số đa thức. Chương trình tham khảo như sau:
program bai4vd;
so := so+du* coso;
var n,so,coso: QWord; du :byte;
coso:=coso*10;
begin
end;
writeln('nhap n= '); readln(n);
n := n div 10;
so:=0; coso:=1;
end;
while n>0 do
writeln('Sau khi bo di so 0 va so 5 so
begin
con lai la ', so);
du := n mod 10;
readln;
if (du<>0) and (du <>5) then END.
begin
2.3.3 Vận dụng làm một số bài tập từ các đề thi
Trang


9


Bài 1: Con ốc sên đang ở gốc của một cái cây cao v mét tính từ gốc. Ốc sên muốn
bò lên ngọn cây để ăn những lá non trên đó. Ban ngày ốc sên bò được a mét lên
trên, nhưng ban đêm, khi ngủ nó bị trôi xuống dưới b mét.
Yêu cầu: Cho các số nguyên v, a và b (1 ≤ b < a ≤ v ≤ 10 9). Hãy xác định số
ngày cần thiết để ốc sên lên tới ngọn cây.
Dữ liệu: Vào từ file văn bản snail.inp gồm một dòng chứa 3 số nguyên a, b và v.
Kết quả: Đưa ra file văn bản snail.out một số nguyên – kết quả tìm được [1].
Ví dụ:
snail.inp
snail.out
1
4
5
Hướng dẫn thuật toán: Khi gặp bài này học sinh có kiến thức số học tốt có thể giải
theo cách 1 trong (Bảng 1) dưới đây.
Tuy nhiên giáo viên có thể hướng dẫn cho học sinh thấy được các trường hợp sau:
Nếu a=v thì chỉ mất 1 ngày, ngược lại thì đoạn đường thực sự là v-b, bước đi thực
sự của con ốc là |a-b|, vậy nếu v-b mà chia hết cho |a-b| thì thương của phép chia đó
là số ngày, ngược lại thì phải mất thêm một ngày nữa, tức là lấy thương đó cộng 1.
Từ đó định hướng để học sinh viết chương trình theo cách 2 trong (Bảng 1).
Cách 1
Cách 2
PROGRAM b1;
end
const fi='snail.inp';
const fi='snail.inp';

else
fo='snail.out';
fo='snail.out';
begin
var f1,f2:text;
var a,b,v,tg:longint;
tg:=tg+a-b;
a,b,v:int64;
dem:longint;
dem:=dem+1; BEGIN
f1,f2:text;
end;
assign(f1,fi); reset(f1);
BEGIN
end;
assign(f2,fo); rewrite(f2);
assign(f1,fi);
write(f2,dem);
readln(f1,a,b,v);
reset(f1);
close(f1);
if a=v then
assign(f2,fo);
close(f2);
writeln(f2,1)
rewrite(f2);
END.
else
read(f1,a,b,v);
if (V-b) mod abs(a-b) = 0 then

tg:=0;dem:=0;
writeln(f2, (v-b) div abs(a-b))
while tgelse
begin
writeln(f2, ((v-b) div abs(aif tg+a=v then
b))+1);
begin
close(f1);close(f2);
dem:=dem+1;
END.
break
(Bảng 1)
Trang 10


Bài 2: Một số được gọi là số bậc thang nếu biểu diễn thập phân của nó có nhiều
hơn một chữ số đồng thời theo chiều từ trái qua phải, chữ số đứng sau không nhỏ
hơn chữ số đứng trước. Viết chương trình in ra các số bậc thang trong đoạn [N1,
N2] với (10Dữ liệu vào: Ghi trong tệp Bai2.inp gồm 1 dòng duy nhất chứa 2 số nguyên dương
N1, N2 (2 số cách nhau một dấu cách).
Dữ liệu vào: Ghi vào tệp Bai2.out các số bậc thang tìm được, mỗi số cách nhau 1
dấu cách.
Bai2.inp
Bai2.out
10 30
11 12 13 14 15 16 17 18 19 22 23 24 25 26 27 28
29
Bài này liên quan đến tính chất bậc thang của một số nên nếu học sinh đã học

chương trình con giáo viên có thể cho các em viết hàm kiểm tra xem một số có là
số bậc thang hay không?
Hướng dẫn thuậ toán: Để kiểm tra một số có là số bậc thang hay không chỉ cần
kiểm tra xem tất cả các số dư sau có lớn hơn số dư trước hay không? Vì vậy ta
dùng một biến kiểm tra để đánh dấu việc so sánh này, nếu tồn tại một trường hợp
mà số dư sau lớn hơn số dư trước thì ghi nhận lại giá trị cho biến kiểm tra, thoát
không cần phải kiểm tra tiếp. Quá trình đó lặp lại cho đên khi thương <10 (vì theo
yêu cầu của đề bài)
Chương trình tham khảo:
Program So_bac_thang;
const fi='bai2.inp';
fo='bai2.out';
Var i,n1,n2: integer;
f1, f2 : text;
Function SBT(n:integer):Boolean;
Var kt: boolean;
sodu:byte;
Begin
kt:=true;
While n>=10 do
Begin
sodu:=n mod 10;
n:=n div 10;
if sodu< (n mod 10) then begin kt:=false; break;end;
End;
SBT:=kt;
End;
Begin
Trang 11



assign(f1,fi);reset(f1);
assign(f2,fo);rewrite(f2);
Readln(f1,n1,n2);
For i:= n1 to n2 do if SBT(i) then Write(f2,i, ' ' );
close(f1);close(f2);
End.
Bài 3: Năm 1973, nhà Toán học Neil Sloan đưa ra khái niệm độ bền của một số
nguyên không âm N như sau: Nếu N có một chữ số thì độ bền của N bằng 0. Nếu N
có từ 2 chữ số trở lên thì độ bền của N bằng độ bền của số nguyên là tích các chữ
số của N cộng 1. Cho N, tìm số bé hơn N có độ bền lớn nhất (0 ≤ N ≤106) [1].
Ví dụ
Persist.inp persist.out Giải thích
100
77
Doben(77)=Doben(49)+1=Doben(36)+1+1=Doben(18)+
1+1+1=Doben(8)+1+1+1+1=0+1+1+1+1=4
Với bài này ta hướng dẫn cho học sinh xây dựng hàm độ bền của một số như sau:
Gọi tich là số cần tính độ bền, ban đầu tich = n, nếu tich <10 thì độ bền bằng 0,
ngược lại lặp lại cách tính tích mới vào biến t, tăng biến độ bền lên 1 đơn vị, gán lại
giá trị biến t cho biến tich, quá trình đó lặp lại cho đến khi tich <10 thì dừng.
Từ giải thích trong đề bài học sinh có thể hiểu đúng và vận dụng đúng để viết
chương trình, có thể như sau:
PROGRAM b3;
const fi='persist.inp';
fo='persist.out';
var n,tong:int64;
i,imax:longint;
dbmax:int64;
f1,f2:text;

{++++++++++++++++++++++}
function doben(n:int64):longint;
var t,tich:int64;
begin
tich:=n;
if tich<10 then doben:=0
else
begin
doben:=0;
repeat
t:=1;
repeat
t:=t*(tich mod 10);
Trang 12


tich:=tich div 10;
until tich=0;
doben:=doben+1;
tich:=t;
until tich<10;
end;
end;
{+++++++++++++++++++++}
BEGIN
assign(f1,fi);
reset(f1);
assign(f2,fo);
rewrite(f2);
readln(f1,n);

dbmax:=doben(1);
for i:=2 to n do
if doben(i)>dbmax then
begin
dbmax:=doben(i);
imax:=i;
end;
write(f2,imax);
close(f1);
close(f2);
END.
Nếu học sinh có tố chất tốt có thể yêu cầu học sinh về nhà sửa lại chương trình
để mở rộng phạm vi của N lên 2 tỷ, tức (0<=N<=2.000.000.000).
Bài 4. Tính tổng chữ số.
Một quyển sách có N trang (N<1000). Hãy cho biết tổng tất cả các chữ số đã
ghi trên các trang sách và mỗi chữ số xuất hiện bao nhiêu lần.
Dữ liệu vào cho trong tệp Bai4.inp gồm 1 dòng duy nhất ghi số nguyên N.
Dữ liệu ra : Ghi vào tệp Bai4.out dòng 1 ghi tổng tất cả các chữ số, dòng 2 ghi
số lần xuất hiện của mỗi chữ số [1].
Ví dụ :
Bai4.inp
15

Bai4.out
66
1822221111
Hướng dẫn thuật toán: Với mỗi số i từ 1 đến N ta dùng phép toán div, mod tách các
chữ số của số i, với mỗi chữ số dư đó ta cộng dồn vào biến tổng, ta dùng mảng đếm
Trang 13



các chữ số đó, vì các số được tách ra (số dư) nằm trong phạm vi từ 0 đến 9 nên ta
chỉ cần khai báo một mảng đếm gồm 10 phần tử với chỉ số từ 0 đến 9 để đếm số
lượng các số dư.
PROGRAM b4;
const fi='bai4.inp';
fo='bai4.out';
var dem:array[0..9] of longint;
n,i,j,t,k:longint;
tong:int64;
f1,f2:text;
BEGIN
assign(f1,fi);
reset(f1);
assign(f2,fo);
rewrite(f2);
readln(f1,n); tong:=0;
for j:=0 to 9 do dem[j]:=0;
for i:=1 to n do
begin
k:=i;
while k<>0 do
begin
t:=k mod 10;
tong := tong + t;
dem[t]:=dem[t]+1;
k:=k div 10;
end;
end;
writeln(f2,tong);

for i:=0 to 9 do write(f2, dem[i],' ');
close(f1);
close(f2);
END.
Bài5. Giai thừa.
Cho số tự nhiên n.
P=n!. Cho biết:
a) P có bao nhiêu chữ số không tận cùng.
b) Số khác 0 tận cùng của P là chữ số nào.
Dữ liệu vào cho trong tệp Bai5.inp gồm 1 dòng duy nhất ghi số nguyên N.
Dữ liệu ra : Ghi vào tệp Bai5.out dòng 1 ghi số lượng chữ số 0 tận cùng, dòng 2
ghi chữ số khác 0 tận cùng của P [1].
Trang 14


Ví dụ :
Bai5.inp
6

Bai5.out
1
2

+ Phân tích đề bài:
a) Việc tính N! của một số khi N lớn sau đó đếm số lượng số 0 là rất khó khăn, do
đó người ta tính bằng cách đếm số lượng các ước số 5 của các số trong tích các số:
1*2*3...*N=N!. Tức là số chữ số 0 cuối cùng chính là số ước bằng 10 của P mà
P=N!= a.10k=a.2k.5k.
Do số ước 2 nhiều hơn ước 5, nên số lượng số 0 tận cùng là K. Vậy ta cần tính số
lượng ước 5 của P.

+ Ví dụ mô phỏng với N=6, N!=1*2*3*4*5*6=720, ta thấy:
Với các số m=1,2,3,4,5,6 thì chỉ có m=5 là chia hết cho 5 nên số lượng số 0 sẽ là 1,
vậy khi duyệt các số m để kiểm tra xem có chia hết cho 5 hay không ta chi cần
duyệt các số m>=5 trở đi là được.
+ Thuật toán: s5:=0; với s5 là số ước 5 của P.
. For m:=5 to n do
Begin
K:=m;
While k mod 5 = 0 do Begin Inc(s5); k:=k div 5 End;
End;
Vậy kết quả cần in ra la: S5.
b) Do cần tìm chữ số cuối khác 0 cuối cùng nên mỗi lần thực hiện việc nhân, chia
ta chỉ giữ lại chữ số khác 0 cuối cùng của tích.
Giả sử S2, s5 là số lượng ước 2 và ước 5 của P.
+ Ví dụ mô phỏng với N=6, N!=1*2*3*4*5*6=720, ta thấy:
Với các số m=2,3,4,5,6 không cần xét m=1 vì 1 nhân với số nào cũng không đổi.
Giá trị K
của M (ban
đầu)

S2=0

M=2
K=2
M=3
K=3
M=4
K=4
M=5
K=5

M=6
K=6
Vậy S2=4, S5=1

S2=1
S2=1
S2=3
S2=3
S2=4

S5=0 K (Sau khi thực hiện việc Ban đầu P=1
chia nguyên số M liên tiếp Công thức tính
cho các ước 2 và 5)
(P:=P*K mod 10)
(chỉ giữ lại chữ số
cuối cùng của P)
S5=0 K=1
P=1
S5=0 K=3
P=3
S5=0 K=1
P=3
S5=1 K=1
P=3
S5=1 K=3
P=9

Trang 15



Thực hiện việc nhân số 2 vào P số lần là S2-S5 (vì số lượng ước số 2 nhiều hơn ước
số 5 là S2-S5, việc nhân số 2 này S2-S5 lần sẽ làm thay đổi chữ số khác 0 cuối
cùng cùng của P), mỗi lần chỉ giữ lại một chữ số cuối cùng của tích ta được
Số lần
P (trước khi chia dư)
P (sau khi chia dư lấy 1 số dư cuối
Công thức: P=P*2 mod 10 cùng)
I=1
P=9*2=18
(9*2 mod 10) = 8
I=2
P=8*2=16
(8*2 mod 10) = 6
I=3
P=6*2=12
(6*2 mod 10) = 2
Vậy chữ số cuối khác 0 của 6! là 2
+ Thuật toán: Giả sử S2, s5 là số lượng ước 2 và ước 5 của P.
S2:=0; S5:=0; P:=1;
For m:=2 to n do
Begin
K:=m;
While K mod 2 = 0 do Begin inc(s2); k:= k div 2 End;
While K mod 5 = 0 do Begin inc(s5); k:= k div 5 End;
P:=P* K mod 10;
End;
For i:= 1 to s2-s5 do p:=p * 2 mod 10;
Vậy kết quả cần in ra là: P
Giáo viên lấy thêm ví dụ:
14! = 87178291200, có chữ số cuối cùng khác 0 là 2 [1].

15! = 1307674368000, có chữ số cuối cùng khác 0 là 8 [1].
const fi='bai5.inp';
fo='bai5.out';
var m,i,n,p,s2,k,s5:longint;
f1, f2 : text;
BEGIN
Assign(f1,fi);reset(f1);
readln(f1,N); close(f1);
Assign(f2,fo);rewrite(f2);
S2:=0; S5:=0; P:=1;
For m:=2 to n do
Begin
K:=m;
While K mod 2 = 0 do Begin inc(s2); k:= k div 2 End;
While K mod 5 = 0 do Begin inc(s5); k:= k div 5 End;
P:=P* K mod 10;
End;
For i:= 1 to s2-s5 do p:=p * 2 mod 10;
Trang 16


writeln(f2,s5);
writeln(f2, p);
close(f2);
END.
Bài 6: Lũy thừa.
Viết chương trình cho phép đọc dữ liệu từ tệp bai6.inp gồm một dòng duy
nhất chứa 3 số nguyên dương Q, M, P. Tìm và ghi kết quả vào tệp bai6.out số dư
khi chia QM cho P [1].
Ví dụ:

Bai6.inp Bai6.out
Giải thích
354
3
35 chia 4 dư 3 (243 chia 4 dư 3)
436
4
43 chia 6 dư 4 (64 chia 6 dư 4)
Hướng dẫn thuật toán:
Việc tìm số dư của QM cho P tức là tìm số dư của tích:
Q*Q*...Q cho P
M lần
Không mất tính tổng quát, ta đặt sodu= Q mod P, do đó mỗi lần (trong M-1 lần còn
lại) ta chỉ việc lấy số dư trước đó nhân với Q và chỉ giữ lại chữ số cuối cùng của
tích đó để thực hiện nhân lần sau. Quá trình đó lặp lại M-1 lần. Vậy giá trị cuối
cùng của biến sodu chính là số dư cần tìm.
Program Luy_thua;
Const fi= 'bai6.inp';
Fo= 'bai6.out';
Var M,Q,P,i,sodu:integer;
F1,f2 : text;
BEGIN
Assign(f1,fi);reset(f1);
Assign(f2,fo);rewrite(f2);
Readln(f1, Q, M , P);
Close(f1);
sodu:=Q mod P;
For i:=1 to M-1 do
Begin
sodu:=(sodu*Q) mod P;

End;
Writeln(f2,sodu);
Close(f2);
END.
Yêu cầu Học sinh về nhà làm các bài tương tự:
Trang 17


-Tìm chữ số tận cùng của 2N với N nhập từ bàn phím [1].
-Tìm số dư khi chia N! cho K với N, K nhập từ bàn phím [1].
Bài 7: NUMBER
Hãy tìm số nguyên dương nhỏ nhất có chữ số hàng đơn vị là d (1≤d≤ 9) sao cho
nếu chuyển chữ số hàng đơn vị lên trước chữ số đầu tiên thì ta được một số mới
gấp k lần số cũ (1≤ k ≤ 9).
Dữ liệu vào: NUMBER.INP
- Gồm nhiều dòng, mỗi dòng chứa hai số nguyên dương d, k cách nhau ít
nhất một dấu cách.
Dữ liệu ra: NUMBER.OUT
- Gồm nhiều dòng, mỗi dòng ghi một số nguyên duy nhất tìm được ứng với
d, k ở dòng tương ứng của file dữ liệu. Ghi -1 nếu không có số thỏa mãn hoặc số
lượng chữ số của số cần tìm quá lớn (lớn hơn 100).
Ví dụ:
NUMBER.INP
NUMBER.OUT
84
205128
Ghi chú: 50% số test có kết quả không vượt quá 106.
Giải thích ví dụ: Với d=8, k=4:
Ta sẽ phải tìm được số ban đầu là 205128. Bởi vì sau khi đổi chữ số hàng đơn vị
(d=8) lên trước chữ số đầu tiên ta được số 820512 và 820512=205128* 4

Ngoài số 205128, ta tìm thêm được nhiều số khác thỏa mãn, ví dụ như:
205128205128, 205128205128205128 ….. Nhưng chọn số 205128 vì nó là số nhỏ
nhất [2].
Hướng dẫn thuật toán:
Với bài này ta hướng dẫn học sinh tìm ra quy luật để xây dựng số cần tìm bằng
phép toán div, mod như sau:
Lần 1: ta lấy (d*k) = 8*4 =32 , ta giữ lại chữ số 2 vào số cần tìm (32 mod 10 = 2),
còn lưu 3 vào biến nhớ để tiếp tục lần 2 (32 div 10 = 3), ta đặt X1:=2; nho:=3;
Lần 2: ta lại lấy chữ số X1 nhân với k cộng với số nhớ ở lần 1;
X1*k = 2 *4 + 3 = 11 (X1 tìm được ở lần 1, 3 là số nhớ ở lần 1);
Ta lại đặt x2 := 11 mod 10 = 1, khi đó biến nho := 11 div 10 =1 để tiếp tục lần 3;
....
Cứ lặp đi lặp lại nhiều lần như vậy cho đến khi tìm được chữ số Xi = d và nho=0 thì
dừng.
Từ quy luật đó ta thấy: Theo yêu cầu của đề bài (khi kết quả lơn hơn 100 chữ số)
thì ta phải sử dụng một mảng một chiều lớn hơn 100 phần tử để lưu lại các chữ số
này, sau khi tìm được ta sẽ in ngược mảng này để tìm kết quả.
Ví dụ với d=8, k=4 thì mảng X như sau:
Chỉ số: 1
2
3
4
5
X
2
1
5
0
2
Trang 18



Khi in ngược ta được: 20512, ghi thêm chữ số d vào cuối cùng ta sẽ thu được kết
quả cần tìm là: 205128
Ban đầu ta đặt nho=0; X[0] =0 để tránh lỗi truy cập phần tử. Vậy X[i] := (X[i-1]*K
+ nho) mod 10; số nhớ sẽ được tính lại như sau:
nho := (X[i-1]*K + nho) div 10; Với i>=1;
Chương trình tham khảo:
program NUMBER;
const
fi='number.inp';
fo='number.out';
var d,k,nho,i: longint;
n: longint;
x: array[0..110] of longint;
f1, f2 :text;
kt:boolean;
BEGIN
assign(f1,fi); reset(f1);
assign(f2,fo); rewrite(f2);
while not seekeof(f1) do
begin
readln(f1,d,k);
x[0]:=d; nho:=0; kt :=false;
for i:=1 to 110 do
begin
x[i]:=(x[i-1]*k+nho) mod 10;
nho:=(x[i-1]*k+nho) div 10;
if (x[i]=d) and (x[i-1]>0) and (nho=0) then
begin

n:=i-1;
kt :=true; break; {luu lai vi tri tim duoc x[i]=d}
end;
end;
if kt=false then n:=-1;
if n=-1 then writeln(f2,n) else
begin
for i:=n downto 1 do write(f2,x[i]);
writeln(f2,d);
end;
end;
close(f1); close(f2);
END.
Trang 19


2.4. Hiệu quả của sáng kiến kinh nghiệm đối với hoạt động giáo dục, với bản
thân, đồng nghiệp và nhà trường
Trong các năm học vừa qua với việc “Hướng dẫn học sinh sử dụng các
phép toán DIV, MOD để rèn luyện kỹ năng lập trình” như phần trên đã trình bày
tôi đã thu được những kết quả bước đầu đáng khích lệ. Dựa trên năng lực và ý thức
chấp hành của học sinh tôi đã phát huy được điểm mạnh của các em khi rèn luyện
kỹ năng lập trình, các em đã đạt được kết quả đúng với năng lực của các em. Kết
quả của cách làm đó dược các đồng nghiệp trong nhóm Tin học ghi nhận và đánh
giá cao.
3. Kết luận, kiến nghị
- Một số kết luận:

Trong quá trình nghiên cứu tôi xin rút ra một số kết luận sau:
+ Để bồi dưỡng học sinh giỏi đạt hiệu quả trước hết giáo viên phải có kỹ năng

thực hành và thiết kế kịch bản bồi dưỡng tốt.
+ Thực sự tâm huyết với công việc bồi dưỡng học sinh giỏi.
+ Giáo viên nên tham khảo thêm các đề thi học sinh giỏi của các tỉnh các năm
trước.
+ Tham khảo nhiều sách báo tài liệu có liên quan, giao lưu học hỏi các bạn
đồng nghiệp có nhiều kinh nghiệm, các trường có bề dày thành tích.
+ Giáo viên phải khơi dậy niềm say mê, hứng thú của học sinh đối với môn tin
học, luôn phối hợp với giáo viên chủ nhiệm và gia đình để tạo điều kiện tốt nhất
cho các em tham gia học tập.
- Kiến nghị:

+ Đối với nhà trường BGH nên chú trọng hơn công tác khảo sát, lựa chọn học
sinh và phân bổ các đối tượng học sinh cho các môn để bồi dưỡng học sinh giỏi.
+ Đối với các cấp cũng nên ra các dạng đề thi phong phú, phù hợp với khả
năng và trình độ của học sinh, không nên ra đề quá sức đối với học sinh.
XÁC NHẬN CỦA THỦ TRƯỞNG
Thanh Hóa, ngày 25 tháng 05 năm 2017
ĐƠN VỊ
Tôi xin cam đoan đây là SKKN của mình viết,
không sao chép nội dung của người khác.
(Ký và ghi rõ họ tên)

Lê Văn Khánh

Trang 20


TÀI LIỆU THAM KHẢO
[1]. Một số tài liệu trên mạng Internet
- Nguồn vn.spoj.com

- Nguồn
- Nguồn
[2]. Đề thi HSG tỉnh Hà Nam năm 2013-2014

Trang 21


DANH MỤC
CÁC ĐỀ TÀI SÁNG KIẾN KINH NGHIỆM ĐÃ ĐƯỢC HỘI ĐỒNG ĐÁNH
GIÁ XẾP LOẠI CẤP PHÒNG GD&ĐT, CẤP SỞ GD&ĐT VÀ CÁC CẤP
CAO HƠN XẾP LOẠI TỪ C TRỞ LÊN
Họ và tên tác giả: Lê Văn Khánh
Chức vụ và đơn vị công tác: Trường THPT Hoằng Hóa 3
TT
1.

2.

3.

4.

Tên đề tài SKKN
Chương trình quản lý nề nếp
dạy – học ở trường THPT.
Rèn luyện kỹ năng lập trình
Môn Tin học 11 cho học sinh
khá, giỏi bằng việc mở rộng các
bài toán cơ bản.
Hướng dẫn học sinh áp dụng

phương pháp sinh giải một số
bài toán liệt kê cơ bản trong Tin
học.
Hướng dẫn học sinh rèn luyện
kỹ năng giải các bài toán về dãy
con liên tiếp.

Kết quả
Cấp đánh
đánh giá
giá xếp loại
xếp loại

Năm học
đánh giá xếp
loại

Sở

C

2012

Sở

C

2013

Sở


C

2014

Sở

C

2016

Trang 22



×