1. Trang chủ
  2. » Luận Văn - Báo Cáo

skkn cấp tỉnh tạo test ngẫu nhiên cho một số bài toán ôn thi học sinh giỏi bằng ngôn ngữ lập trình c

22 1 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Nội dung

Trang 1

SỞ GIÁO DỤC VÀ ĐÀO TẠO THANH HÓA

TRƯỜNG THPT HOẰNG HÓA 4 - -

SÁNG KIẾN KINH NGHIỆM

ĐỀ TÀI

“TẠO TEST NGẪU NHIÊN CHO MỘT SỐ BÀI TOÁNÔN THI HỌC SINH GIỎI BẰNG NGÔN NGỮ

LẬP TRÌNH C++”

Người thực hiện: Trương Ngọc Huy

SKKN thuộc môn: Tin học

THANH HOÁ NĂM 2024

Trang 2

1.3 Đối tượng nghiên cứu: 1

1.4 Phương pháp nghiên cứu: 1

1.5 Những điểm mới của sáng kiến kinh nghiệm: 2

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: 3

2.3 Các giải pháp đã sử dụng để giải quyết vấn đề: 3

2.3.1 Tạo một số, kí tự ngẫu nhiên sử dụng hàm srand và rand: 3

a Tạo một số nguyên ngẫu nhiên có giá trị thuộc đoạn [0, x]: 3

b Tạo một số nguyên ngẫu nhiên có giá trị thuộc đoạn [-x, x]: 4

c Tạo số nguyên ngẫu nhiên từ x đếm y(x<y): 4

d Tạo một kí tự ngẫu nhiên: 4

e Tạo một số thực ngẫu nhiên: 5

2.3.2 Tạo một số, xâu kí tự ngẫu nhiên sử dụng cách thức khác: 5

a Tạo số nguyên ngẫu nhiên sử dụng lớp mt19937 hoặc mt19937_64: 5

b Tạo số nguyên ngẫu nhiên sử dụng lớp default_random_engine và uniform_int_distribution: 6

c Tạo số thực ngẫu nhiên: 6

d Tạo xâu kí tự ngẫu nhiên: 6

2.3.3 Tạo mãng N số ngẫu nhiên, xâu kí tự có độ dài ngẫu nhiên: 7

a Tạo mảng a gồm N số ngẫu nhiên không âm: 7

b Tạo mảng a gồm N số ngẫu nhiên: 8

c Tạo mảng a gồm N số nguyên ngẫu nhiên từ x đến y: 8

d Tạo mảng a gồm N số thực ngẫu nhiên: 8

e Tạo xâu kí tự có độ dài ngẫu nhiên: 9

f Tạo mảng a gồm N xâu kí tự có độ dài ngẫu nhiên: 10

2.3.4 Một số bài toán hay dùng trong ôn thi học sinh giỏi: 11

Bài toán 1: Tạo mảng ngẫu nhiên tăng 11

Bài toán 2: Tạo mảng cấp số cộng 11

Bài toán 3: Tạo ngẫu nhiên mảng có tỉ lệ 1:k 12

Bài toán 4: Tạo ngẫu nhiên đều 13

Bài toán 5: Tạo xâu đối xứng ngẫu nhiên 14

2.4 Hiệu quả của sáng kiến kinh nghiệm: 15

Trang 4

1 MỞ ĐẦU1.1 Lí do chọn đề tài:

Trong mọi thời đại, giáo dục luôn đóng vai trò vô cùng quan trọng Đó là

nền tảng, là động lực cho sự phát triển của một quốc gia Để đào tạo thế hệ trẻ

trở thành người chủ thực sự của đất nước trong tương lai, có khả năng làm chủđược nền khoa học kỹ thuật hiện đại, thì việc đổi mới nội dung và phươngpháp dạy học là vấn đề hết sức cấp thiết Một trong những biện pháp giúp đổimới phương pháp dạy học hiện nay là ứng dụng công nghệ thông tin trong dạyhọc và trong đời sống xã hội Với sự giúp đỡ của máy vi tính và các phần mềmdạy học, giáo viên sẽ tổ chức tốt quá trình dạy học trên lớp theo hướng phát huytính tích cực, chủ động, sáng tạo trong hoạt động nhận thức của học sinh.

Trong quá trình tham gia giảng dạy và bồi dưỡng học sinh giỏi môn Tinhọc ở trường, tôi thấy việc tạo test để chấm bài cho học sinh là một công việchết sức quan trọng Vì khi tham gia các kì thi liên quan đến lập trình trong Tinhọc thì chúng ta cần có test để chấm Để có được test chấm thì chúng ta phảitạo ra các test bằng tay hoặc bằng code tạo ra file input của bài toán, từ fileinput của bài toán ta chạy trương trình code chuẩn hoặc code trâu để sinh rafile output đúng Một bộ test chuẩn là bộ test phải vét được tất cả các trườnghợp của bài toán.

Chính vì vậy tôi nhận thấy để đánh giá chính xác được thuật toán của 1bài toán trong Tin học có tối ưu hay không thì việc tạo test là rất quan trọng Đó

chính là lý do, tôi đã chọn đề tài "Tạo test ngẫu nhiên cho một số bài toán ônthi học sinh giỏi bằng ngôn ngữ lập trình C++" để nghiên cứu.

1.2 Mục đích nghiên cứu:

Tạo ra một số chương trình tạo test để chấm các bài toán cơ bản và nângcao trong quá trình ôn thi học sinh giỏi Giúp học sinh tìm ra các thuật toán tốiưu hơn và giúp giáo viên chấm bài một cách nhanh chóng và hiệu quả.

1.3 Đối tượng nghiên cứu:

- Các khái niệm về hàm và các phương thức khác có liên quan đến tạo testngẫu nhiên;

- Học sinh khối 10 và một số học sinh ôn thi học sinh giỏi của trườngTHPT Hoằng Hóa 4.

1.4 Phương pháp nghiên cứu:

- Tìm hiểu các hàm và các phương thức khác có liên quan đến tạo testngẫu nhiên;

- Sáng kiến kinh nghiệm của tôi đang trình bày dựa theo các phương phápnhư: Thuyết trình, quan sát, phân tích thuật toán, … phù hợp với bài học và mônhọc thuộc lĩnh vực Tin học.

Trang 5

1.5 Những điểm mới của sáng kiến kinh nghiệm:

- Hiện nay có nhiều giáo viên giảng dạy môn Tin học hoặc những em họcsinh muốn học về lập trình nhưng chưa biết cách tạo test để chấm bài chochương trình của mình hay của học sinh Vì vậy khi biết tạo file input ngẫunhiên thì công việc tạo test chấm bài được thực hiện một cách nhanh chóng vàhiệu quả hơn.

- Đề tài này tôi đã vận dụng thêm một số phương thức khác để tạo test

ngoài hàm rand() và vận dụng vào một số bài toán cụ thể để tạo test nhằm tối

ưu thuật toán.

2 NỘI DUNG SÁNG KIẾN KINH NGHIỆM2.1 Cơ sở lý luận của sáng kiến kinh nghiệm:

Từ nghị quyết số 29/NQ-TW tại Hội nghị Trung ương 8 khóa XI về đổimới căn bản, toàn diện giáo dục và chỉ thị 40/CT của Ban bí thư Trung ươngĐảng, sở GD&ĐT đã tập trung chỉ đạo đổi mới các hoạt động kiểm tra, đánh giáthúc đẩy đổi mới phương pháp dạy học nhằm tạo sự chuyển biến cơ bản về tổchức hoạt động dạy học, góp phần nâng cao chất lượng giáo dục trong các nhàtrường.

Môn tin học có nhiều đặc thù khác nhau, khác nhau ở từng cấp học, khốilớp Từ người bắt đầu sử dụng máy tính, đến người đã sử dụng thành thạo máytính Tuy nhiên cấp học cao hơn thì chương trình học cũng cao hơn Một sự khácbiệt nửa của môn Tin học là Lý thuyết – Bài tập – Thực hành hay nói cách kháclà Nói – Làm – Có kết quả, nói chung phải đạt cả ba Chẳng hạn dạy học lậptrình người dạy dạy lý thuyết hay, giải bài tập hay và thực hành cho kết quảminh chứng, nhưng nếu khi thực hành trên máy không cho kết quả như mongmuốn thì chữ hay đó chắc chắn không trọn vẹn.

Mặt khác tuy môn Tin học mới đưa vào chương trình phổ thông bắt từnăm 2006, nhưng hiện nay có rất nhiều học sinh biết những kiến thức cơ bản vềthông tin và các công nghệ cao là những kiến thức rất cần thiết đối với mỗingười nhất là thế hệ trẻ hiện nay Vì vậy các em đã đam mê hơn với môn Tinhọc và muốn học lập trình để theo ngành công nghệ thông tin Nhưng do điềukiện kinh tế của gia đình không mua được máy tính cho học sinh cũng như cơ sởvật chất của nhà trường còn thiếu nên cơ sở vật chất để giảng dạy môn học nàycũng không dễ mua sắm Từ những bất cập đó mà trình độ hiểu biết về lập trìnhnói riêng và tin học nói chung trong nhà trường còn hạn chế.

Một trong những hạn chế ở đây là học sinh sau khi lập trình giải quyếtđược 1 bài toán trong tin học nhưng không biết có đúng theo yêu cầu của bàitoán không và làm sao biết để tối ưu được thuật toán của bài toán đã cho? Điềunày đã hối thúc tôi tìm tòi và nghiên cứu để tìm ra giải pháp nhằm mục đích dạytốt hơn trong quá trình ôn thi học sinh giỏi nói riêng và học lập trình nói chungtrong nhà trường.

Trang 6

2.2 Thực trạng vấn đề trước khi áp dụng sáng kiến kinh nghiệm:

Ngày nay phần lớn học sinh biết sử dụng máy tính và có máy tính cá nhânmỗi ngày một tăng, trình độ hiểu biết và sử dụng máy tính cũng tăng rõ rệt.Nhiều em đã định hướng được ngành nghề cho tương lai nên đã đam mê hơn vớimôn Tin học, nhất là lập trình giải quyết các bài toán trong Tin học Đồng thờinhiều em cũng muốn được vào đội tuyển thi học sinh giỏi cấp Tỉnh của trường

Tuy nhiên cơ sở vật chất của nhà trường không đáp ứng được các tiết thựchành và tài liệu học tập của môn Tin học trong nhà trường còn khá ít Thời gianhọc tập trên trường cũng hạn chế nên phần lớn các em học và làm bài tập ở nhànhưng không biết chương trình của mình đã đúng với yêu cầu của đề bài chưa.

Chính vì vậy để biết một chương trình đã đúng chưa và làm sao để tránhsai sót và tối ưu được thuật toán thì cần phải có nhiều bộ test khác nhau và vétđược hết các trường hợp của bài toán cho Đó chính là thực trạng của của vấn đềtrước khi áp dụng sáng kiến kinh nghiệm này.

2.3 Các giải pháp đã sử dụng để giải quyết vấn đề:

Trong ngôn ngữ lập trình C++ hàm rand() tạo một số nguyên ngẫu nhiêntrong đoạn [0, RAND_MAX], trong đó RAND_MAX là một hằng số có sẵn có

giá trị phụ thuộc vào chương trình dịch Giá trị lớn nhất của số nguyên tạo ra bởi

rand() là RAND_MAX, thường là 32767 Dựa vào hàm rand này tôi đưa ra một

số chương trình tạo test cho một số bài tập đơn giản và nâng cao trong các bàitập bồi dưỡng học sinh giỏi Trước khi gọi hàm rand ta cần gọi hàm srand để

khởi tạo bộ số ngẫu nhiên Tuy nhiên C++ còn cung cấp nhiều cách thức để tạo

dữ liệu ngẫu nhiên khác như sử dụng lớp mt19937, mt19937_64,

default_random_engine, uniform_real_distribution, uniform_int_distribution

sẽ được tôi lồng ghép vào một số nội dung,

2.3.1 Tạo một số, kí tự ngẫu nhiên sử dụng hàm srand và rand:

a Tạo một số nguyên ngẫu nhiên có giá trị thuộc đoạn [0, x]:

freopen("SND.INP","w", stdout); //Ghi giá trị vào file SND.INP

int x = 100;

cout << n; return 0;}

Trang 7

b Tạo một số nguyên ngẫu nhiên có giá trị thuộc đoạn [-x, x]:

freopen("SNDXX.INP","w", stdout); //Ghi giá trị vào file SNDXX.INP

int x = 100;

int n = rand()%(x+1) - rand()%(x+1);//Tạo số nguyên thuộc đoạn -x x(-100 100) cout << n;

return 0;}

c Tạo số nguyên ngẫu nhiên từ x đếm y(x<y):

Ta có rand()%(y-x+1) tạo số nguyên ngẫu nhiên từ 0 đếm y-x do đóx+rand()%(y-x+1) tạo các số từ x đến x+y-x=y Từ nhận xét đó ta có đoạnchương trình sau:

freopen("SNDXY.INP","w", stdout); //Ghi giá trị vào file SNDXY.INP

int x = 10, y = 1000;

int n = x + rand()%(y-x+1); //Tạo số nguyên thuộc đoạn x y(10 1000)

cout << n; return 0;}

d Tạo một kí tự ngẫu nhiên:

Ta có các kí tự trong bảng mã ASCII có mã thập phân tử 0 đến 255 do đóta sử dụng cách ép kiểu nguyên về kí tự Cách ép kiểu nguyên về kí tự như sau

freopen("KITU.INP","w", stdout); //Ghi giá trị vào file KITU.INP

Trang 8

cout << n;

//cout<<(char)(97+rand()%(122-97+1)); //Tạo ra 1 chữ cái in thường ngẫu nhiên //cout<<(char)(65+rand()%(90-65+1)); //Tạo ra 1 chữ cái in Hoa ngẫu nhiên //cout<<(char)(48+rand()%(57-48+1)); //Tạo ra 1 số ngẫu nhiên

return 0;}

e Tạo một số thực ngẫu nhiên:

freopen("SOTHUC.INP","w", stdout); //Ghi giá trị vào file SOTHUC.INP

float x = 1, y = 100;

float n = x + z*(y-x); //Tạo số thực trong đoạn [x, y](1, 100)

cout << fixed<<setprecision(2)<<n; return 0;

Khi chúng ta thay đổi kiểu dữ liệu và tùy theo bài toán ta có thể tạo ra cáctest để kiểm tra tính đúng đắn của các bài toán mà học sinh làm Việc tạo một sốngẫu nhiên, một kí tự ngẫu nhiên sẽ giúp giáo viên tạo các test cho các bài toánôn luyện học sinh giỏi một cách dễ dàng từ đó có thể đánh giá các giải thuật củahọc sinh một cách chính xác.

2.3.2 Tạo một số, xâu kí tự ngẫu nhiên sử dụng cách thức khác:

a Tạo số nguyên ngẫu nhiên sử dụng lớp mt19937 hoặc mt19937_64:

Lớp mt19937sử dụng để tạo ra số nguyên 32-bit, lớp mt19937_64 sửdụng để tạo ra số nguyên 64-bit Sau đây là chương trình minh họa cách sửdụng 2 lớp này.

Chương trình:

#include <bits/stdc++.h>

using namespace std;int main(){

ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

freopen("SONGUYEN.INP","w", stdout); //Ghi giá trị vào file SONGUYEN.INP

mt19937 mt(time(0)); int a = mt();

cout << a; return 0;

Trang 9

ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

freopen("SONGUYEN.INP","w", stdout); //Ghi giá trị vào file SONGUYEN.INP

default_random_engine re(time(0));

uniform_int_distribution<int> unif(1, 100); int a = unif(re);

cout << a; return 0;}

c Tạo số thực ngẫu nhiên:

Hàm randvà lớp mt19937 chỉ tạo ra số nguyên, để tạo ra số thực bạnphải sử dụng phép nhân số nguyên tạo ra với 1.0 và sau đó chia các số tạo racho nhau Một cách khác để tạo ra số thực ngẫu nhiên là sử dụng lớp

default_random_engine, uniform_real_distribution tương tự như với sốnguyên Sau đây là chương trình minh họa tạo số thực ngẫu nhiên có giá trịtrong đoạn [1, 1000].

Chương trình:

#include <bits/stdc++.h>

using namespace std;int main(){

ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

freopen("SOTHUC.INP","w", stdout); //Ghi giá trị vào file SONTHUC.INP default_random_engine re(time(0));

uniform_real_distribution<double> unif(1, 1e3); double a = unif(re);

cout<<fixed<<setprecision(2)<<a; return 0;

d Tạo xâu kí tự ngẫu nhiên:

Để tạo xâu kí tự ngẫu nhiên, ta thực hiện theo các bước như sau:- Định nghĩa một xâu/mảng kí tự làm bảng kí tự từ điển;

- Sử dụng cấu trúc lặp gọi hàm tạo số ngẫu nhiên nhiều lần, lấy giá trị số

Trang 10

ngẫu nhiên đó chia lấy phần dư cho một số(thường là tổng số kí tự của bảng kítự từ điển) cho để làm chỉ số truy cập lấy kí tự ngẫu nhiên từ bảng kí tự từ điển.

Sau đây là chương trình minh họa tạo ra xâu kí tự ngẫu nhiên có độ dàitối đa 100 kí tự là chữ latin viết thường và chỉ có 4 kí tự là: ‘a’, ‘b’, ‘c’, ‘d’:

Chương trình:

#include <bits/stdc++.h>

using namespace std;int main(){

ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);

freopen("XAUKITU.INP","w", stdout); //Ghi giá trị vào file XAUKITU.INP mt19937 mt(time(0));

string dict = "abcd"; //Từ điển

string rnds = ""; //Xâu ngẫu nhiên tạo ra int len = mt() % 100; //Độ dài xâu

for (int i = 1; i <= len; i++){ int j = mt() % 4;

rnds += dict[j]; }

cout << rnds; return 0;}

2.3.3 Tạo mãng N số ngẫu nhiên, xâu kí tự có độ dài ngẫu nhiên:

Tạo ngẫu nhiên N số, kí tự ngẫu nhiên sử dụng kiểu dữ liệu mảng để lưu

a Tạo mảng a gồm N số ngẫu nhiên không âm:

freopen("ARRD.INP","w", stdout); //Ghi giá trị vào file ARRD.INP

int x = 100, y = 1000;

int n = rand()%(x+1);//Tạo số lượng phần tử thuộc đoạn 0 x(0 100)

cout<<n<<endl;

for(int i = 1; i <= n; i++){

a[i] = rand ()%(y+1); //Tạo số nguyên dương thuộc đoạn 0 y(0 1000) cout <<a[i]<<" ";

}

return 0;}

Trang 11

b Tạo mảng a gồm N số ngẫu nhiên:

freopen("ARRAD.INP","w", stdout); //Ghi giá trị vào file ARRAD.INP

int x = 100, y = 1000;

int n = rand()%(x+1); //Tạo số lượng phần tử thuộc đoạn 0 x(0 100)

cout<<n<<endl;

for(int i = 1; i <= n; i++){

a[i] = rand ()%(y+1) - rand ()%(y+1); //Tạo số nguyên dương thuộc đoạn -y y(-1000 1000)

cout <<a[i]<<" "; }

return 0;}

c Tạo mảng a gồm N số nguyên ngẫu nhiên từ x đến y:

Dựa vào nhận xét của mục 2.3.1 c ta có thủ tục tạo n số nguyên ngẫunhiên tử x đến y(x<y) như sau:

freopen("ARRXY.INP","w", stdout); //Ghi giá trị vào file ARRXY.INP

int z = 100, x = 10, y = 1000;

int n = rand()%(z+1);//Tạo số lượng phần tử thuộc đoạn 0 z(0 100)

cout<<n<<endl;

for(int i = 1; i <= n; i++){

a[i] = x + rand()%(y-x+1); //Tạo số nguyên dương thuộc đoạn x y(10 1000) cout <<a[i]<<" ";

}

return 0;}

d Tạo mảng a gồm N số thực ngẫu nhiên:

Sử dụng đoạn chương trình tạo một số thực ở mục 2.3.1 e ta sẽ có một

Ngày đăng: 13/06/2024, 20:24

w