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

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

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 (213.08 KB, 22 trang )

<span class="text_page_counter">Trang 1</span><div class="page_container" data-page="1">

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

<b>TRƯỜNG THPT HOẰNG HÓA 4------</b>

SÁNG KIẾN KINH NGHIỆM

<b>ĐỀ TÀI</b>

<b>“TẠO TEST NGẪU NHIÊN CHO MỘT SỐ BÀI TỐNƠN THI HỌC SINH GIỎI BẰNG NGƠN NGỮ</b>

<b>LẬP TRÌNH C++” </b>

<b> </b>

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

<b>SKKN thuộc mơn: Tin học</b>

THANH HỐ NĂM 2024

</div><span class="text_page_counter">Trang 2</span><div class="page_container" data-page="2">

<b>1.3. Đối tượng nghiên cứu:...1</b>

<b>1.4. Phương pháp nghiên cứu:...1</b>

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

<b>2. NỘI DUNG SÁNG KIẾN KINH NGHIỆM...2</b>

<b>2.1. Cơ sở lý luận của sáng kiến kinh nghiệm:...2</b>

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

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

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 tố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 tố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

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

</div><span class="text_page_counter">Trang 4</span><div class="page_container" data-page="4">

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

Trong mọi thời đại, giáo dục ln đóng vai trị vơ cùng quan trọng. Đó là

<i>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ẻ</i>

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 q 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 tốn.

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

<i><b>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.</b></i>

<b>1.2. Mục đích nghiên cứu:</b>

Tạo ra một số chương trình tạo test để chấm các bài tốn cơ bản và nângcao trong q trình ơn thi học sinh giỏi. Giúp học sinh tìm ra các thuật tố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ả.

<b>1.3. Đối tượng nghiên cứu:</b>

- 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.

<b>1.4. Phương pháp nghiên cứu:</b>

- 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 tốn, … phù hợp với bài học và mônhọc thuộc lĩnh vực Tin học.

</div><span class="text_page_counter">Trang 5</span><div class="page_container" data-page="5">

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

- 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

<b>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</b>

ưu thuật toán.

<b>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:</b>

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, tồ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 tốn trong tin học nhưng khơng biết có đúng theo u cầu của bàitố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 q 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.

</div><span class="text_page_counter">Trang 6</span><div class="page_container" data-page="6">

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

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 tố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 tố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 tố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.

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

<b>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ó</b>

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

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

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 để

<b>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</b>

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

<i><b>default_random_engine, uniform_real_distribution, uniform_int_distribution</b></i>

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

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

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

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

<b>int</b> x = 100;

cout << n; <b>return</b> 0;}

</div><span class="text_page_counter">Trang 7</span><div class="page_container" data-page="7">

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

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

<b>int</b> x = 100;

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

<b>return</b> 0;}

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

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

<b>int</b> x = 10, y = 1000;

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

cout << n; <b>return</b> 0;}

<i><b>d. Tạo một kí tự ngẫu nhiên:</b></i>

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

</div><span class="text_page_counter">Trang 8</span><div class="page_container" data-page="8">

cout << n;

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

<b>return</b> 0;}

<i><b>e. Tạo một số thực ngẫu nhiên:</b></i>

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

<b>float</b> x = 1, y = 100;

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

cout << fixed<<setprecision(2)<<n; <b>return</b> 0;

Khi chúng ta thay đổi kiểu dữ liệu và tùy theo bài tố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 tố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.

<b>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:</b>

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

<b>Lớp mt19937sử dụng để tạo ra số nguyên 32-bit, lớp mt19937_64</b> 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.

<i><b>Chương trình:</b></i>

#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); <i><small>//Ghi giá trị vào file SONGUYEN.INP</small></i>

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

cout << a; return 0;

</div><span class="text_page_counter">Trang 9</span><div class="page_container" data-page="9">

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

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

default_random_engine re(time(0));

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

cout << a; return 0;}

<i><b>c. Tạo số thực ngẫu nhiên:</b></i>

<b>Hàm randvà lớp mt19937</b> 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

<b>default_random_engine, uniform_real_distribution</b> 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].

<i><b>Chương trình:</b></i>

#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;

<i><b>d. Tạo xâu kí tự ngẫu nhiên:</b></i>

Để 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ố

</div><span class="text_page_counter">Trang 10</span><div class="page_container" data-page="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’:

<i><b>Chương trình:</b></i>

#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;}

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

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.

<i><b>a. Tạo mảng a gồm N số ngẫu nhiên không âm:</b></i>

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

<b>int</b> x = 100, y = 1000;

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

cout<<n<<endl;

<b>for</b>(<b>int</b> 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]<<" ";

}

<b>return</b> 0;}

</div><span class="text_page_counter">Trang 11</span><div class="page_container" data-page="11">

<i><b>b. Tạo mảng a gồm N số ngẫu nhiên:</b></i>

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

<b>int</b> 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;

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

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

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

<b>return</b> 0;}

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

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

<b>int</b> z = 100, x = 10, y = 1000;

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

cout<<n<<endl;

<b>for</b>(<b>int</b> 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]<<" ";

}

<b>return</b> 0;}

<i><b>d. Tạo mảng a gồm N số thực ngẫu nhiên:</b></i>

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

</div>

×