SKKN Áp dụng thuật toán sàng nguyên tố để giải một số bài tập về số nguyên tố trong Tin học nhằm nâng cao chất lượng bồi dưỡng học sinh giỏi ở trường trung học phổ thông 4 Thọ Xuân 1 1 PHẦN MỞ ĐẦ[.]
Trang 11 PHẦN MỞ ĐẦU 1.1 Lý do chọn đề tài
Công tác bồi dưỡng học sinh giỏi là một công tác mũi nhọn trong việc nâng cao chất lượng giáo dục, tạo nguồn lực, bồi dưỡng nhân tài cho nhà trường nói riêng, cho địa phương nói chung Đồng thời, thông qua kết quả học sinh giỏi phần nào khẳng định được vị thế của trường so với các trường bạn trong huyện nói riêng và trong tỉnh nói chung
Bồi dưỡng học sinh giỏi là một công việc khó khăn và lâu dài, đòi hỏi nhiều công sức của thầy và trò Đặc biệt là những trường có chất lượng đầu vào của học sinh thấp nhất huyện như trường chúng tôi thì giấc mơ để học sinh có giải trong các kì thi học sinh giỏi Tỉnh là quá xa vời
Chất lượng học sinh giỏi môn Tin học của trường từ năm học 2011 – 2012 trở về trước là rất thấp, môn Tin học luôn trong tình trạng “trắng bảng”, chưa có học sinh nào đạt được giải học sinh giỏi môn Tin học cấp tỉnh, mặc dù một số năm vẫn có học sinh tham gia thi Chất lượng học sinh giỏi môn Tin học còn thấp như vậy, phần vì năng lực học sinh, phần vì phương pháp giảng dạy của giáo viên chưa phù hợp Do đó việc nâng cao chất lượng học sinh giỏi môn Tin học là cần thiết và cấp bách nhằm góp thêm vào thành tích chung của nhà trường
Mặt khác, trong quá trình dạy bồi dưỡng học sinh giỏi tôi gặp rất nhiều bài toán về số nguyên tố Đây là dạng bài tập không khó và thường xuất hiện trong các đề thi học sinh giỏi môn Tin học Tuy nhiên rất nhiều học sinh khi gặp dạng bài tập này bị mất điểm hoặc điểm không cao Nguyên nhân có thể nhiều nhưng trong đó có nguyên nhân cơ bản là: chương trình cho kết quả output sai hoặc chương trình cho kết quả output đúng nhưng chỉ với các bộ input có dữ liệu nhỏ còn với những bộ input có dữ liệu lớn thì chương trình chạy quá thời gian quy định mặc dù kết quả output vẫn đúng
Với mong muốn giúp học sinh giải quyết tốt hơn các bài tập về số nguyên
tố và hiểu biết sâu sắc hơn cách sử dụng giải thuật sàng nguyên tố, tôi đã dày công nghiên cứu, tìm tòi các bài tập có nội dung liên quan cũng như các đề thi của các tỉnh, trăn trở để tìm ra nhiều cách làm để học sinh biết các vận dụng để chương trình tối ưu nhất và dễ hiểu nhất Từ đó nâng cao chất lượng bồi dưỡng học sinh giỏi môn Tin học
Từ những lý do trên tôi đã mạnh dạn trình bày sáng kiến kinh nghiệm: “Áp dụng thuật toán sàng nguyên tố để giải một số bài tập về số nguyên tố trong Tin học nhằm nâng cao chất lượng bồi dưỡng học sinh giỏi ở trường trung học phổ thông 4 Thọ Xuân” để học sinh dễ dàng làm quen, tiếp thu và hình
thành các kỹ năng trong việc tiếp cận các bài toán về số nguyên tố
1.2 Mục đích của đề tài
Mục đích của đề tài này là cung cấp một cách tiếp cận mới trong việc giải quyết các bài toán về số nguyên tố một cách tối ưu, đồng thời đưa ra các ví
dụ để học sinh có thể làm quen, hình thành các kĩ năng trong việc tiếp cận và giải các bài toán có sử dụng sàng nguyên tố của Eratosthenes
Trang 21.3 Đối tượng nghiên cứu.
Các bài toán liên quan đến số nguyên tố, được nghiên cứu ở nhiều tài liệu
và các đề thi qua các năm được giải quyết bằng cách sử dụng sàng nguyên tố của Eratosthenes
Học sinh lớp 11 trường THPT 4 Thọ Xuân
1.4 Phương pháp nghiên cứu
Sáng kiến kinh nghiệm đang trình bày của tôi dựa theo các luận cứ khoa học hướng đối tượng, vận dụng linh hoạt các phương pháp: quan sát, thuyết trình, vấn đáp, điều tra cơ bản, kiểm thử, phân tích kết quả thực nghiệm sư phạm,v.v… phù hợp với bài học và môn học thuộc lĩnh vực cấu trúc dữ liệu Tham khảo các bài tập tin học, bài tập Tin học nâng cao, tài liệu ôn luyện học sinh giỏi và một số đề thi học sinh giỏi môn Tin học
Nghiên cứu các tài liệu liên quan đến sàng nguyên tố của Eratosthenes và rút ra phương pháp để làm quen với bài tập dạng này
Hướng dẫn cho học sinh làm quen và hình thành kĩ năng để giải một số bài toán cụ thể
Kiểm tra, đánh giá kết quả của học sinh trong quá trình triển khai đề tài để
từ đó có những điều chỉnh, bổ sung hợp lí
Trang 32 NỘI DUNG NGHIÊN CỨU 2.1 Cơ sở lý luận
Căn cứ vào mục tiêu của môn Tin học, là phải cung cấp những tri thức cơ bản, làm nền tảng để học sinh có thể tiếp tục đi sâu vào tìm hiểu và xây dựng khoa học Tin học hoặc tiếp thu những tri thức của các lĩnh vực kĩ thuật công nghệ tiên tiến, nhất là các lĩnh vực của công nghệ thông tin, đặc biệt là trong giai đoạn với nhiều thời cơ và không ít thách thức của cuộc cách mạng công nghiệp 4.0 hiện nay Nó hội tụ nhiều công nghệ, trong đó cốt lõi là công nghệ thông tin Công nghệ thông tin xuất hiện trong hầu khắp các lĩnh vực, như: kinh tế chia sẻ 4.0, dịch vụ thông minh, nông nghiệp thông minh 4.0, y tế thông minh 4.0, giáo dục thông minh 4.0, giao thông thông minh 4.0,…[1]
2.2 Thực trạng
Năm đầu tiên tôi tham gia công tác bồi dưỡng học sinh giỏi, việc dạy đội tuyển của tôi chủ yếu dựa trên những kiến thức cơ bản của sách giáo khoa, chưa biết cách cải tiến để chương trình tối ưu hơn để chương trình chạy nhanh hơn và chủ yếu là định hướng cho học sinh tìm ra được thuật toán để chương trình cho
ra được kết quả mà thôi Do đó kết quả học sinh giỏi năm đó chưa được như mong muốn, có 2 em học sinh tham gia thi học sinh giỏi Tin của trường và không có em nào đạt giải Bản thân các em và giáo viên không hiểu vì sao kết quả lại thấp như vậy vì khi đi thi về các em rất phấn khởi vì thấy mình làm bài tốt, thấy bài của mình vẫn cho kết quả đúng giống trong đề nhưng tại sao điểm lại thấp như vậy Và cuối cùng tôi cũng đã hiểu ra rằng khi giải quyết các bài toán về số nguyên tố nói riêng và các bài tập lập trình pascal khác nói chung, học sinh và ngay cả giáo viên thường chỉ làm việc với các bộ input có dữ liệu nhỏ dễ nhìn thấy kết quả output và thường không xét đến trường hợp input đặc biệt hay các input có dữ liệu lớn Dẫn đến bị mất điểm trong bài thi học sinh giỏi
Vấn đề đặt ra, là làm thế nào để lấy được điểm với các bộ input có dữ liệu lớn Muốn vậy cần phải lựa chọn và cài đặt được chương trình hiệu quả nhất
2.3 Các biện pháp sử dụng để giải quyết vấn đề
2.3.1 Cơ sở lý thuyết
a Cơ sở lý thuyết
Số nguyên tố: Là số tự nhiên chỉ có hai ước số dương phân biệt là 1 và chính
nó [2]
Hợp số: Là một số tự nhiên có thể biểu diễn thành tích của hai số tự nhiên khác nhỏ hơn nó Một định nghĩa khác tương đương: hợp số là số chia hết cho các số khác ngoài 1 và chính nó [3]
Sàng nguyên tố : Là thuật toán do Eratosthenes đưa ra để tìm các số nguyên tố
Nó có đặc điểm khác với thuật toán khác là kiểm tra các số nguyên tố theo kiểu sàng lọc, xét tất cả những số cần kiểm, những số nào không phải là số nguyên tố thì bỏ đi Thuật toán thích hợp cho bài toán tìm tất cả các số nguyên tố trong khoảng [a, b] mà đặc biệt hiệu quả khi khoảng cách giữa a, b là rất lớn Eratosthenes (tiếng Hy Lạp: Ερατοσθένης; 276 TCN – 194 TCN) là một nhà toán học, địa lý và thiên văn người Hy Lạp [4]
Trang 4b Hình thức của sàng Eratosthenes
Ban đầu, nhà toán học Eratosthenes sau khi tìm ra thuật toán, đã lấy lá cọ
và ghi tất cả các số từ 2 cho đến 100 Ông đã chọc thủng các hợp số và giữ nguyên các số nguyên tố Bảng số nguyên tố còn lại trông rất giống một cái sàng Do đó, nó có tên là sàng Eratosthenes [4]
c Giải thuật
Xét từ 2 đến N
Bắt đầu với i=2
Trong khi i< Trunc(sqrt(N)) thì:
+ Xóa bội của i, khác i
+ Tìm tiếp i đầu tiên chưa xóa
Cuối cùng các điểm chưa bị xóa là số nguyên tố.[4]
Minh họa cho bảng N=100 như sau:
Ban đầu Kết quả sau khi sàng nguyên tố
Minh họa thuật toán
2 4;6;8;10;12;14;16;18;20;22;24;26;28;30;3
2;34;36;38;40;42;44;46;48;50;52;54;56;5 8;60;62;64;66;68;70;72;74;76;78;80;82;8
4;86;88;90;92;94;96;98;100
3 9;15;21;27;45;51;57;63;69;75;87;93;99
11;13;17;19;23;29;31;
37;41;43;47;53;59;61;
67;71;73;79;83;89;97
Không có bội nào trong bảng trên
Vậy ta sàng được các số nguyên tố trong đoạn [1;100] là: 2; 3;5;7;11;13;17;19;23;29;31;37;41;43;47;53;59;61;67;71;73;79;83;89;97
Trang 5d Cài đặt
Cách 1
Const
nmax=1000;
var
SNT:array[0 nmax+1] of boolean;
procedure sangnt;
var i,j:longint;
begin
fillchar(snt,sizeof(snt),true);
snt[1]:=false;
i:=2;
while i<=trunc(sqrt(nmax)) do
begin
while snt[i]=false do
inc(i);
for j:=2 to nmax div i do
snt[i*j]:=false;
inc(i);
end;
Cách 2
procedure sangnt;
begin
fillchar(kt, sizeof(kt), true);
kt[1]:= false;
for i:=2 to trunc(sqrt(maxn)) do
if kt[i] then
for j:= 2 to maxn div i do
kt[i*j]:= false;
end;
2.3.2 Bài tập vận dụng
Bài 1: Viết chương trình in ra các số nguyên tố từ 2 đến N.[5]
Thuật toán: Dùng thuật toán sàng nguyên tố để tìm đánh dấu tất cả các số
nguyên tố bé hơn hoặc bằng N Rồi duyệt từ 1 đến N Nếu là số nguyên tố thì in ra
Chương trình
Program Bai1;
Const n=1000;
Var SNT:array[0 n+1] of boolean;
procedure sangnt;
var i,j:longint;
begin
fillchar(snt,sizeof(snt),true); snt[1]:=false; i:=2;
Trang 6while i<=trunc(sqrt(n)) do
begin
while snt[i]=false do inc(i);
for j:=2 to n div i do
snt[i*j]:=false; inc(i);
end;
for i:=1 to n do
if snt[i]=true then
write(i,' ');
end;
begin
sangnt;
readln;
end
Bài 2 Số nguyên tố [6]
Cho dãy số gồm có N số nguyên dương a1, a2, , aN và một số nguyên dương K
Yêu cầu: Hãy cho biết số lượng các phần tử có giá trị nhỏ hơn K là số nguyên tố
của dãy số trên
Dữ liệu: Dòng đầu tiên là hai số N và K.
Dòng tiếp theo lần lượt là N số nguyên của dãy số
Kết quả: Gồm duy nhất số M là số lượng các phần tử của dãy số thoả mãn yêu
cầu đề bài
Giới hạn: 0 < N < 108; 0 < K < 106, |ai| < 109 < i = 1 N;
Ví dụ:
7 8
1 2 3 8 7 6 11
3
Thuật toán: Dùng thuật toán sàng nguyên tố để tìm đánh dấu tất cả các số
nguyên tố bé hơn 106 Rồi duyệt tất cả các phần tử của mảng, chỉ xét các phần tử
có giá trị bé hơn K, nếu nó là số nguyên tố thì tăng kết quả lên
Chương trình
Program bai2;
const maxn=round(1e6);
var n,i,j,k,dem:longint; kt:array[1 maxn] of boolean;
a:array[1 100000000] of longint;
Begin
fillchar(kt,sizeof(kt),true);
kt[1]:=false;
for i:=2 to trunc(sqrt(maxn)) do
if kt[i]=true then
for j:=2 to maxn div i do
Trang 7kt[i*j]:=false;
readln(n,k); dem:=0;
For i:=1 to n do
begin
readln(a[i]);
if( kt[a[i]]=true) and (a[i]<k) then inc(dem);
end;
writeln('so luong',dem);
readln
end
Bài 3 Tìm mật khẩu (Trích- Bài 2 đề thi học sinh giỏi tỉnh lớp 12 THPT Năm
học 2014-2015 Tỉnh Thanh Hóa) [6]
Việc bảo vệ máy tính của mình để hạn chế người khác thâm nhập vào là một vấn đề đặt ra cho mọi người sử dụng máy tính Để tăng tính an toàn trong lưu trữ Lan đã quyết định đặt mật khẩu truy cập máy tính của mình vào một xâu
T với một quy ước sao cho khi cần cô ta có thể lấy lại được mật khẩu từ xâu T như sau:
Là một người yêu thích số học cô ta thường chọn mật khẩu P là một số nguyên
tố và đem giấu vào trong một xâu ký tự T sao cho P chính là số nguyên tố có giá trị lớn nhất trong số các số nguyên tố được tạo từ các xâu con của T (xâu con của một xâu ký tự T là một chuỗi liên tiếp các ký tự trong T)
Ví dụ: xâu T= “Test1234#password5426” chứa mật khẩu là 23 vì T chứa các xâu con ứng với các số nguyên tố 2, 3, 23 và 5
Yêu cầu: cho một xâu ký tự T có chiều dài không quá 500 ký tự Tìm mật khẩu
P đã dấu trong xâu T biết P có giá trị nhỏ hơn 105 Dữ liệu cho đảm bảo luôn có P
Dữ liệu vào: vào từ file văn bản BAI2.INP gồm 1 dòng duy nhất là xâu T.
Kết quả: ghi ra file văn bản BAI2.OUT là số P tìm được.
Ví dụ:
Test1234#password5426 23
Thuật toán: Vì bài toán luôn có đáp số và kết quả của bài toán luôn nhỏ hơn
105 nên ta dùng thuật toán sàng nguyên tố để tìm đánh dấu tất cả các số nguyên
tố nhỏ hơn 105 rồi cho i chạy từ 105 -1 về 2, nếu i là số nguyên tố và i có trong xâu thì in ra i và kết thúc luôn chương trình
Chương trình
Program bai3;
const maxn= round(1e5);
var st: ansistring; st1: string; i,j: longint; kt: array[1 maxn] of boolean; f,g:text;
procedure sangnt;
begin
fillchar(kt, sizeof(kt), true);
Trang 8kt[1]:= false;
for i:=2 to trunc(sqrt(maxn)) do
if kt[i] then
for j:= 2 to maxn div i do
kt[i*j]:= false;
end;
BEGIN
assign(f, 'bai2.inp'); reset(f); assign(g, 'bai2.out'); rewrite(g);
readln(f, st);
sangnt;
for i:= 100000-1 downto 2 do
if kt[i] then
begin
str(i,st1);
if pos(st1,st)<>0 then
begin
write(g, st1); halt;
end;
end;
close(f);
close(g);
END.
Bài 4: Số nguyên tố lớn thứ nhì (Trích Bài 3 đề thi giáo viên dạy giỏi THPT
cấp tỉnh năm 2017 – 2018 Tỉnh Thanh Hóa)
Hôm nay trời bỗng dưng mưa to, Bờm không thể đi học được, vì nhà Bờm quá
xa trường Nếu đi học Bờm sẽ bị ướt hết người nên Bờm quyết định lấy sách Tin học lớp 11 ra để tự học Ngồi học được một lúc, Bờm nghĩ ra một bài toán để ngày mai lên lớp đố các bạn Bài toán như sau: Cho một dãy số nguyên không
âm A1, A2, A3, , AN-1, AN Hãy tìm giá trị của số nguyên tố lớn thứ nhì của tất
cả các số nguyên tố được lấy từ dãy số trên Để hiểu rõ hơn về số nguyên tố lớn thứ nhì thì Bờm lấy 2 ví dụ sau:
+ Ví dụ 1: Xét dãy số gồm 6 số sau: 11, 2, 2, 4, 5, 7 Thì số nguyên tố lớn thứ
nhì là 7 Giải thích: dãy trên ta có các số nguyên tố là 2, 5, 7, 11; thì số nguyên
tố lớn nhất là 11, số nguyên tố lớn thứ nhì là 7
+ Ví dụ 2: Dãy số nguyên gồm 4 số sau: 1, 2, 2, 0 Thì dãy số này không có số
nguyên tố thứ nhì Giải thích: Vì không có số nguyên tố nào nhỏ hơn 2
Yêucầu: Các bạn hãy thử giải bài toán trên của Bờm.
Dữ liệu vào:Từ file văn bản BAI3.INP gồm
- Dòng đầu tiên chứa một số nguyên dương N (N ≤ 106)
- Dòng thứ hai gồm N số nguyên không âm A 1 , A 2 , A 3 , , A N-1 , A N (A i≤ 106, với mọi i=1,2, N)
Dữ liệu ra: Ghi ra file văn bản BAI3.OUT là một số nguyên là kết quả của bài
toán Nếu không có số nguyên tố lớn thứ nhì thì in ra số -1
Trang 9Ví dụ
6
11 2 2 4 5 7
1 2 2 0
-1
Thuật toán dùng thuật toán sàng nguyên tố để tìm đánh dấu tất cả các số
nguyên tố nhỏ hơn 106 Rồi duyệt các phần tử của mảng và sử dụng thuật toán lùa bò vào chuồng
Chương trình
Program bai4;
Const maxN= round(1e6);
Var a: array[0 maxn+1] of longint; f: array[0 maxn+1] of boolean; i,n: longint; tim: longint; h,g:text;
procedure sangnt;
var i,j: longint;
Begin
for i:= 2 to maxn do f[i]:= true;
f[0]:= false; f[1]:= false;
for i:=2 to trunc(sqrt(maxn)) do
if f[i] then
for j:= 2 to maxn div i do
f[i*j]:= false;
End;
BEGIN
assign(h ,'bai3.inp'); reset(h);
assign(g, 'bai3.out'); rewrite(g);
readln(h,n); sangnt; tim:=-1;
for i:=1 to n do
begin read(h, a[i]);
if f[a[i]] then
if tim<a[i] then tim:= a[i];
end;
for i:= 1 to n do
if tim = a[i] then f[a[i]]:= false; tim:= -1;
for i:=1 to n do
if f[a[i]] then
if tim<a[i] then tim:= a[i];
writeln(g, tim);
close(h); close(g);
END
Trang 10Bài 5: Số siêu nguyên tố( Trích Kì thi chọn học sinh giỏi tỉnh lớp 12 THPT
năm học 2012 – 2013 môn Tin học Tỉnh Hải Dương) [7]
Số siêu nguyên tố là số nguyên tố mà khi xoá bỏ dần các chữ số bên phải của nó thì phần còn lại vẫn là số nguyên tố Ví dụ: 2333 là số siêu nguyên tố vì 2333,
233, 23, 2 đều là các số nguyên tố
Yêu cầu: Cho số nguyên dương M (M ≤ 30000) Hãy tìm số siêu nguyên tố gần với M nhất, tức là trị tuyệt đối của hiệu giữa số tìm được với M là nhỏ nhất)
Dữ liệu: Nhập vào từ bàn phím số nguyên dương M (không cần kiểm tra dữ liệu
nhập)
Kết quả: Ghi ra màn hình các số nguyên tố gần M nhất, mỗi số một dòng theo
thứ tự số nhỏ hơn ghi trước
Ví dụ:
31
Thuật toán: dùng thuật toán sàng nguyên tố để tìm đánh dấu tất cả các số
nguyên tố nhỏ hơn 30000 Rồi xây dựng chương trình con kiểm tra một số có phải là số siêu nguyên tố hay không Sau đó xét 2 trường hợp của số nguyên tố gần M nhất là số đứng trước và số đứng sau
Chương trình:
Program BAI5;
Var d: array[1 30000] of byte; M: longint; var a, b: longint;
Procedure sangNT;
Var i,j: longint;
Begin
for i:=1 to 30000 do d[i]:=0;
d[1]:=1; i:=1;
while i*i<=30000 do
begin
repeat inc(i) until (i*i>30000) or (d[i]=0);
if i*i<=30000 then
begin
j:=2;
while i*j<=30000 do
begin
d[i*j]:=1; inc(j);
end;
end;
end;
End;
Function sieunt(x: longint): boolean;
Begin
repeat
if d[x]=1 then