Tải bản đầy đủ (.docx) (26 trang)

skkn cấp tỉnh phương pháp giải một số bài toán số học bồi dưỡng học sinh giỏi tin học bằng ngôn ngữ 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 (151.65 KB, 26 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Ố

<b>PHỊNG GIÁO DỤC VÀ ĐÀO TẠO NƠNG CỐNG</b>

SÁNG KIẾN KINH NGHIỆM

<b>PHƯƠNG PHÁP GIẢI MỘT SỐ BÀI TOÁN SỐ HỌC BỒI DƯỠNG HỌC SINH GIỎI TIN HỌC BẰNG NGÔN</b>

<b>NGỮ C++--- </b>

<b>Người thực hiện: Lê Thị HoaChức vụ: Giáo viên</b>

<b>Đơn vị công tác: Trường THCS Trần PhúSKKN thuộc lĩnh mực (mơn): Tin học</b>

<b>NƠNG CỐNG, NĂM 2024</b>

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

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

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

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

2.3 Các sáng kiến kinh nghiệm hoặc các giải pháp đã sử dụng đểgiải quyết vấn đề

2.3.6 Xử lý bài toán với kiểu dữ diệu lớn <b>16</b>

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

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

<b>1. MỞ ĐẦU</b>

<b>1.1. Lý do chọn đề tài</b>

Tin học được hình thành và phát triển rất mạnh mẽ, đã trở thành mộtngành khoa học độc lập với các nội dung, mục tiêu, phương pháp nghiên cứuriêng và ngày càng có nhiều ứng dụng trong hầu hết các lĩnh vực hoạt động củaxã hội loài người. Mục tiêu của tin học là khai thác thơng tin có hiệu quả nhấtphục vụ mọi mặt hoạt động của con người. Do đó ở bất kỳ lĩnh vực nào cần xửlý thơng tin thì ở đó tin học đều có thể phát huy tác dụng. Trong ngành giáo dụchiện nay cũng là một ngành đã và đang đưa công nghệ thông tin vào ứng dụngtrong việc dạy và học.

Cấp trung học phổ thông là cấp học cuối cùng của giáo dục phổ thơng cótrách nhiệm hoàn thành vệc đào tạo tiếp thế hệ học sinh của nhà trường phổthông. Đây là cấp học vừa trực tiếp tạo nguồn cho bậc cao đẳng, đại học nóiriêng, vừa góp phần quan trọng vào việc đào tạo nguồn nhân lực phục vụ cơngnghiệp hóa, hiện đại hóa đất nước nói chung. Học sinh THCS là nguồn lao độngtrẻ có thể sử dụng ngay sau khi tốt nghiệp do vậy việc được tiếp cận công nghệthông tin từ trong nhà trường phổ thơng sẽ giúp cho học sinh có thể tự tin hơntrong công việc. Việc đào tạo học sinh có nền tảng lập trình cơ bản và có đammê lập trình có vai trị quan trọng trong sự phát triển sau này của các em. Thôngqua việc dạy đội tuyển học sinh giỏi, dạy những lớp mũi nhọn nhiều năm để họcsinh u thích lập trình tơi rút ra những kinh nghiệm sau: Tạo sự đam mê lậptrình, vận dụng các kiến thức đã học để giải các bài tốn thực tế, hình thành vàphát triển tư duy logic, dạy học thông qua các chuyên đề độc lập hay liên hệgiữa toán học và tin học để giải quyết các bài toán.

Trong nhiều bài toán Tin học, việc vận dụng kiến thức số học giúp đưa rađược những thuật toán tối ưu hơn. Mặt khác, những bài toán Tin học có sự vậndụng kiến thức số học cơ bản, địi hỏi sự cài đặt khơng q phức tạp và các emcó nền tảng Tốn học tốt có thể dễ dàng suy luận được. Từ đó kích thích niềmu thích của các em trong việc lập trình. Các thuật toán số học trong tin học lànội dung kiến thức khá quan trọng và được sử dụng nhiều trong thiết kế thuậttốn. Tuy nhiên, trong q trình giảng dạy tơi thấy học sinh vẫn cịn khó khăntrong việc phân tích bài tốn để có thể áp dụng được thuật tốn và cài đặt giảibài tốn. Vì vậy tơi chọn đề tài này để giúp học sinh có được hệ thống kiến thứccơ bản về toán học để giúp các em dễ dàng hơn trong giải quyết các bài toán cụthể nhất là đối các bài toán về số học.

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

Học sinh được bồi dưỡng thi học sinh giỏi không chỉ cần nắm vững kiếnthức trong sách giáo khoa mà cịn phải có khả năng tư duy tốt để giải quyết cácbài tốn khó. Việc dạy học khơng chỉ là truyền đạt kiến thức cho các em mà giáoviên cịn phải kích thích sự sáng tạo, niềm đam mê học hỏi và muốn tìm hiểu cáimới.

Trong quá trình dạy học sinh và đứng đội tuyển học sinh giỏi tơi thấy rằngnhiều bài tốn sẽ được giải quyết nhanh nếu chúng ta biết cách phân tích từ giảthiết bài tốn, tính chất của các số và áp dụng hợp lý. Với những lý do trên tôi

<i><b>chọn đề tài về “Phương pháp giải một số bài toán số học bồi dưỡng học sinh</b></i>

<i><b>giỏi Tin học bằng ngôn ngữ C++” </b></i>

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

Góp phần đổi mới phương pháp dạy học sinh giỏi mơn Tin học theo hướngphát huy tính tích cực, chủ động và sáng tạo của học sinh giúp học sinh tiếp thutri thức một cách có hiệu quả.

Góp phần gây hứng thú học tập mơn Tin học cho học sinh tham gia thi chọnhọc sinh giỏi, tránh việc học thụ động, học vẹt. Giúp học sinh lĩnh hội tri thứcmột cách khoa học, củng cố và khắc sâu kiến thức.

Đưa ra các thuật toán cơ bản liên quan để giải quyết bài toán số học. Tạo hệthống kiến thức mở cho học sinh tiếp cận và phát huy năng lực tư duy logic,sáng tạo.

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

Học sinh khối 8,9 và đội tuyển học sinh giỏi trường THCS Trần PhúNông Cống.

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

Phương pháp phân tích thuật tốn, kiểm tra đánh giá năng lực học sinh,phát triển tư duy logic. Một số tài liệu tham khảo và tìm kiếm thơng tin trêninternet.

<b>1. NỘI DUNG SÁNG KIẾN</b>

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

Nghị quyết Hội nghị Trung ương 8 khóa XI về đổi mới căn bản, toàn diệngiáo dục và đào tạo nêu rõ: “Tiếp tục đổi mới mạnh mẽ phương pháp dạy học vàhọc theo hướng hiện đại; phát huy tính tích cực, chủ động, sáng tạo và vận dụngkiến thức, kỹ năng của người học; khắc phục kiến thức truyền một chiều, ghinhớ máy móc. Tập trung dạy cách học, cách nghĩ, khuyến khích tự học, tạo cơsở để người học tự cập nhật và đổi mới tri thức, kỹ năng và phát triển năng lực.

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

Chuyển từ học chủ yếu trên lớp sang tổ chức hình thức học tập đa dạng, chú ýhoạt động xã hội, ngoại khóa, nghiên cứu khoa học. Đẩy mạnh ứng dụng côngnghệ thông tin và truyền thông trong dạy và học”.

Quyết định 711/QĐ-TTg ngày 13/6/2012 của Thủ tướng Chính phủ chỉrõ: “Tiếp tục đổi mới phương pháp dạy học và đánh giá kết quả học tập, rènluyện theo hướng phát huy tính tích cực, tự giác, sáng tạo và năng lực tự học củangười học”

Luật Giáo dục số 38/2005/QH11, Điều 28 quy định: “Phương pháp giáodục phổ thông phải phát huy tính tích cực, tự giác, chủ động, sáng tạo của họcsinh; phù hợp với đặc điểm của từng lớp học, môn học; bồi dưỡng phương pháptự học, khả năng làm việc theo nhóm; rèn luyện kỹ năng kiến thức vào thực tiễn;tác động đến tình cảm, đem lại niềm vui, hứng thú học tập cho học sinh”.

Tạo điều kiện cho học sinh chiếm lĩnh những tri thức và kỹ năng Tin họccần thiết và phát triển năng lực trí tuệ chung như: phân tích, tổng hợp, trừutượng hố, khái qt hố… rèn luyện những đức tính, phẩm chất của người laođộng mới. Học sinh sẽ thấy rõ hiệu quả mạnh mẽ của cơng nghệ thơng tin vànhận thức cần có.

Tin học và tốn học có mối liên quan mật thiết với nhau, có ảnh hưởng rấtlớn đến mọi lĩnh vực của cuộc sống. Các bài toán tin nếu được thuật toán trên cơsở lý thuyết toán học vững chắc sẽ đem lại kết quả tốt hơn rất nhiều so với cácthuật tốn khác. Thực tế qua những năm tơi bồi dưỡng đội tuyển học sinh giỏiTin học bắt gặp rất nhiều bài tốn số học cần lập trình trên máy tính. Từ đó tơiđưa ra những phân tích, đánh giá để làm sáng tỏ cho mỗi vấn đề được đề cập tới.Với cách tiếp cận mở như vậy, hy vọng đề tài này sẽ giúp các em học sinh cóđược một hệ thống những kiến thức cần thiết, bổ ích và thiết thực.

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

Sự quan trọng của công nghệ thông tin trong xã hội hiện nay ai cũng biếtnhưng để được sự quan tâm của các em học sinh, phụ huynh, nhà trường là cảmột khó khăn.

Quá trình thực hiện đề tài tại trường THCS Trần Phú tơi có một số thuậnlợi và khó khăn sau:

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

- Được sự giúp đỡ, tạo điều kiện của tổ nhóm chun mơn Tốn – Tin.

<i>* Học sinh:</i>

Nhiều học sinh đã thấy được tiềm năng phát triển của ngành công nghệthông tin trong tương lai, qua đó có ý thức và định hướng về nghề cơng nghệthông tin.

<b>2.3.1 . Ước chung lớn nhất, bội chung nhỏ nhất của 2 số nguyên dương</b>

- Ước số chung lớn nhất (USCLN) của hai số được tính theo thuật tốn Euclid

<i>int ucln(int a, int b) {</i>

<i> int tmp;while(b > 0) {</i>

<i>tmp = a % b;a = b;</i>

<i>b = tmp; }</i>

<i>return a;}</i>

- Sử dụng hàm để tính ước số chung lớn nhất của hai số:

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

<i>_ _gcd(a,b)</i>

- Bội số chung nhỏ nhất (BSCNN) của hai số được tính theo cơng thức:

<i>int bcnn(a,b)</i>

<i>{return (a*b)/ucln(a,b);}</i>

<i><b>Bài tốn: Trực nhật</b></i>

Ở một lớp học có <i><small>n</small></i> học sinh. Mỗi bạn đều phải trực nhật và cứ sau một số

<i><small>y</small></i> ngày nhất định bạn đó mới phải trực nhật lại. Biết rằng xuất phát điểm ban đầutất cả sẽ đều trực nhật vào ngày đầu tiên. Bạn hãy giúp lớp trưởng tính xem saubao nhiêu ngày thì tất cả các bạn mới lại cùng nhau trực nhật và khi đó mỗi bạnđã trực nhật bao nhiêu lần.

<b>Dữ liệu vào đọc từ file tn.inp:</b>

- Dòng đầu chứa số nguyên n <i><small>(2≤ n<100)</small></i>

- Dòng thứ hai chứa n số nguyên <i><small>y</small></i>. <i><small>(1≤ y<100)</small></i>

<b>Dữ liệu ra ghi vào file tn.out:</b>

- Dòng đâu tiên ghi ra số ngày mà tất cả cùng nhau trực nhật lại.

- Dòng thứ hai chứa n số là số lần một bạn đã trực nhật cho tới lúc tất cảcùng trực nhật.

<b>Ví dụ:</b>

32 3 4

126 4 3

<i>long long gcd(long long a, long long b) { if (b == 0) return a;</i>

<i> else return gcd(b, a % b);}</i>

<i>int main(){</i>

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

<i> freopen("tn.inp","r",stdin); freopen("tn.out","w",stdout); long long n;</i>

<i> cin >> n; long long a[n];</i>

<i> for (long long i = 0; i < n; i++) cin >> a[i]; long long bcnn = (a[0]*a[1])/gcd(a[0],a[1]); for (long long i = 2; i < n; i++)</i>

<i> { bcnn = (bcnn * a[i]) / gcd(bcnn, a[i]);} cout << bcnn << endl;</i>

<i> for (long long i = 0; i < n; i++) cout << bcnn / a[i] << " "; return 0;</i>

<b>2.3.2. Kiểm tra tính nguyên tố của một số nguyên dương</b>

Số nguyên tố là số nguyên dương chỉ có 2 ước khác nhau là 1 và chính nó.

<b>Cách 1. Để kiểm tra một số nguyên dương N có là số nguyên tố hay không ta </b>

kiểm tra xem có tồn tại số nguyên k (2 ≤ k ≤ √<i><small>N</small></i>) sao cho k là ước của Nhay không? Nếu tồn tại số ngun k thì N khơng phải số nguyên tố ngược lại Nlà số nguyên tố.

<i>bool kiem_tra(int n){</i>

<i>if (n < 2) return flase;</i>

<i>for(int i = 2; i <= sqrt(n); i++)if(n%i==0) return flase;</i>

<i>return true;}</i>

Tuy nhiên ta thấy cách này khơng hiệu quả vì độ phức tạp cao.

<b>Cách 2. Dùng thuật tốn sàng ngun tố</b>

- Tìm ra số ngun tố i, sàng để loại bỏ tất cả các bội của i.- Dùng mảng đánh dấu p[i], chỉ số i của mảng bắt đầu từ 0. p[i]=0 nếu i không nguyên tố; p[i] =1 nếu i là nguyên tố

Ban đầu phủ mảng nhận giá trị là 1. Sau đó gán giá trị khởi tạo: p[0]=p[1]=0.- Cho i chạy từ 2 đến √<i><small>N</small></i>:

Nếu (i ngun tố) thì loại tồn bộ bội của i ra khỏi mảng p.

<i>void sangngto(int n){ fill(p,p+n+1,1);</i>

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

<b>Cách 3. Để tránh việc phải kiểm tra k có phải là số ngun tố hay khơng ta có</b>

thể dựa vào một trong hai tính chất đơn giản của số nguyên tố sau:- Trừ 2 các số nguyên tố đều lẻ.

<i>if (n==2 || n==3) return true;</i>

<i>if (n==1 || n%2==0 || n%3==0) return false;int k=-1;</i>

<i>while (k<=int(sqrt(n))) { k+=6;</i>

<i> if (n%k==0 || n% (k+2)==0) break;}</i>

<i> return k>int(sqrt(n));}</i>

<b>Bài toán 1. Tìm tất cả các số nguyên tố trong đoạn [1,N] với N≤10</b><small>7</small>

<b>Dữ liệu vào đọc từ file nto.inp:</b>

- Một dòng đầu chứa số nguyên n

<b>Dữ liệu ra ghi vào file nto.out:</b>

- Một dòng ghi ra tất cả các số là số nguyên tố trong đoạn [1,N]

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

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

<i>#include <bits/stdc++.h>#define N int(1e7+1)using namespace std;int p[N];</i>

<i>int n;</i>

<i>void sangngto(int n){ fill(p,p+n+1,1);</i>

<i> freopen("nto.inp","r",stdin); freopen("nto.out","w",stdout); cin>>n;</i>

<i> sangngto(n);</i>

<i> for (int i=2;i<=n;i++)</i>

<i> if(p[i]==1) cout<<i<<" "; return 0;</i>

<b>Bài toán 2. Phân tích một số thành tích ra các thừa số nguyên tố.</b>

<i>Theo định lý cơ bản của số học: Mọi số nguyên dương đều có thể biểu diễn </i>

<i>duy nhất thành tích của các số nguyên tố.</i>

<i>Mọi số tự nhiên N>1 đều có thể biễu diễn duy nhất dưới dạng chuẩn tắc<small>N= p</small></i><small>1</small><i><sup>k1</sup><small>× p</small></i><small>2</small><i><sup>k 2</sup><small>× …× ps</small><sup>ks</sup> trong đó k<small>i</small> là số nguyên dương và p<small>i</small> là các số nguyên tốvới <small>p1< p2<…<ps</small> .</i>

Yêu cầu: Cho một số nguyên dương N (2<N<10<small>9</small>) hãy phân tích N thành tíchcác thừa số nguyên tố.

<b>Dữ liệu vào đọc từ file phantich.inp:</b>

- Một dòng đầu chứa số nguyên n

<b>Dữ liệu ra ghi vào file phantich.out:</b>

- Nhiều dòng, mỗi dòng ghi ra 2 số p và k cách nhau bởi dấu cách.

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

<b>Ví dụ:</b>

<i><b>Thuật tốn:</b></i>

Dùng một mảng p[i] để lưu lũy thừa. Mảng này có giá trị các phần tử banđầu đều bằng 0. Cho i chạy từ 2 đến √<i><small>N</small></i>, nếu n chia hết cho i thì tăng p[i] lên 1.Khi in kiểm tra: Nếu p[i] >0 thì in i^p[i].

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

<i>#include <bits/stdc++.h>#define N int(1e6)</i>

<i>using namespace std;int p[N];</i>

<i> if(p[i]>0) cout<<i<<"^"<<p[i]<<'\n'; if (x>1) cout<<x<<"^"<<"1";</i>

<i>int main()</i>

<i>{ freopen("phtich.inp","r",stdin); freopen("phtich.out","w",stdout); cin>>n;</i>

<i> phantich(n); return 0;}</i>

<b>2.3.3. Đếm số ước của n</b>

Khi N được phân tích thành thừa số nguyên tố như sau:

<i><small>N= p</small></i><small>1</small><i><sup>k1</sup><small>× p</small></i><small>2</small><i><sup>k 2</sup><small>× …× ps</small><sup>ks</sup></i>

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

<b>Ta có các kết luận sau:</b>

Số các ước của N là: <small>(</small><i><small>k 1+1)×</small></i><small>(k 2+1)</small><i><small>×…×(ks+1)</small></i>

<b>Yêu cầu: Cho số nguyên dương n (n ≤ 10</b><small>7</small>). Đếm số ước của n.

<b>Dữ liệu vào đọc từ file demuoc.inp:</b>

- Một dòng đầu chứa số nguyên n

<b>Dữ liệu ra ghi vào file demuoc.out:</b>

- Kết quả là số lượng các ước của n.

<i>#define ll long longusing namespace std;int p[N];</i>

<i> for (int i=2;i<N;i++) if(p[i]>0) d=d*(p[i]+1); if(x>1) d=d*2;</i>

<i> cout<<d;}</i>

<i>int main()</i>

<i>{ freopen("demuoc.inp","r",stdin); freopen("demuoc.out","w",stdout); cin>>n;</i>

<i> phantich(n); return 0;}</i>

<b>2.3.4. Lý thuyết đồng dư</b>

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

(a + b) % m = (a % m + b % m) % m(a-b)%m = (a % m – b % m) % m(a*b)%m = ((a % m) * (b % m)) % m

(a/b)%m = (a * 1/b) % m = (a % m)*(1/b * m)

<b>Bài tốn: Tìm chữ số cuối khác 0 của N!</b>

<b>u cầu: Em hãy viết chương trình tìm chữ số tận cùng khác 0 của n! (với</b>

<b>Dữ liệu vào đọc từ file chuso.inp:</b>

Gồm có nhiều dịng liên tiếp nhau, trên mỗi dịng chứa một số ngunkhơng âm N.

<b>Dữ liệu ra ghi vào file chuso.out:</b>

Có số dịng bằng số dịng tương ứng với dữ liệu vào. Trên mỗi dòng ghichữ số khác khơng cuối cùng của n!.

<b>Ví dụ:</b>

chuso.inp chuso.out24

<b>Thuật tốn:</b>

Các chữ số cuối cùng bằng 0 của n giai thừa được sinh ra khi và chỉ khitrong khai triển ra thừa số ngun tố của tích trên có chứa các cặp thừa số 2 và5. Vậy thì trước hết ta đếm số lượng các thừa số 2, kí hiệu là d2 và số lượng cácthừa số 5, kí hiệu là d5.

Thí dụ, với n = 15 ta có dạng khai triển ra thừa số nguyên tố của n giai thừa nhưsau:

n! = 1.2.3.(2.2).5.(2.3).7.(2.2.2).9.(2.5).11. (2.2.3).13.(2.7).(3.5)

Do đó d2 = 11 và d5 = 3. Vậy ta có ba cặp 2.5 = 10 và số mũ dôi ra củathừa số 2 so với thừa số 5 sẽ là d2 – d5 = 11 – 3 = 8. Khi đó, kết quả sẽ là: chữsố cuối cùng khác 0 của 15! = chữ số cuối cùng của k.2<small>d2-d5</small>.Trong đó k là tíchcủa các thừa số cịn lại.

Dễ thấy với mọi n, ta ln có d2 > d5 vì cứ hai số liên tiếp thì có một sốchẵn (chia hết cho 2), còn năm số liên tiếp mới có một số chia hết cho 5.

Việc cịn lại là lấy tích k của các số cịn lại. Vì tích này khơng bao giờ tậncùng bằng 0 cho nên ta chỉ cần giữ lại một chữ số cuối cùng bằng cách lấy mod10.

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

Để tính chữ số tận cùng của 2<small>m</small> với m = d2 – d5 > 0 ta để ý đến tính tuầnhồn của nó, cụ thể là ta chỉ cần tính chữ số tận cùng của 2(m % 4) với cáctrường hợp:

Lưu ý rằng sử dụng tính chất đồng dư (a.b) % m=((a % m).(b % m)) % mcho nên ta có thể lấy % ở các bước trung gian với số lần tùy ý.

Để tránh việc tràn số khi sử dụng các biến dung lượng nhỏ chúng ta có thể tăngthêm một phép tốn % nữa. Chẳng hạn, khi tích luỹ kết quả, thay vì viết

k = (k*c) % 10; ta nên viết k = (k*(c % 10)) % 10;

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

<i>#include <bits/stdc++.h>#define ll long long</i>

<i>using namespace std;ll n;</i>

<i>ll tim(ll n){</i>

<i> ll k =1, m =0;ll tim = k;</i>

<i> if (n <= 1) return 0;ll d = 0,x;</i>

<i>for (int i = 2;i<=n;i++){x = i;</i>

<i>while (x%2 == 0){m = m+1; x = x/ 2;}while (x%5== 0){m = m-1; x = x/5;}k = (k*(x%10)) %10;}</i>

<i> switch (m % 4)</i>

</div>

×