Sáng kiến kinh nghiệm THPT: Nghiên cứu các cải tiến sàng Eratosthenes và áp dụng giải một số bài toán trong chương trình bồi dưỡng học sinh giỏi Tin học
lượt xem 8
download
Mục tiêu nghiên cứu của sáng kiến kinh nghiệm là trình bày về sàng Eratosthenes và cách cải tiến sàng Eratosthenes để áp dụng giải một số bài toán liên quan.
Bình luận(0) Đăng nhập để gửi bình luận!
Nội dung Text: Sáng kiến kinh nghiệm THPT: Nghiên cứu các cải tiến sàng Eratosthenes và áp dụng giải một số bài toán trong chương trình bồi dưỡng học sinh giỏi Tin học
- MỤC LỤC I. ĐẶT VẤN ĐỀ....................................................................................................... 1 1. Lí do chọn đề tài:............................................................................................... 1 2. Mục đích của đề tài: .......................................................................................... 1 3. Nhiệm vụ của đề tài: ......................................................................................... 1 4. Giới hạn, phạm vi nghiên cứu của đề tài: ......................................................... 1 II. NỘI DUNG ......................................................................................................... 2 1. Định nghĩa số nguyên tố: .................................................................................. 2 2. Thuật toán Vét cạn (Brute Forces).................................................................... 2 3. Sàng nguyên tố Eratosthenes ............................................................................ 3 4. Cải tiến 1 ........................................................................................................... 4 5. Cải tiến 2 ........................................................................................................... 5 6. Cải tiến 3 ........................................................................................................... 5 Kết quả sau cải tiến ............................................................................................... 7 7. Một số bài toán ví dụ áp dụng........................................................................... 7 Bài 1: Factor..................................................................................................... 7 Bài 2. Tổng các số nguyên tố đầu tiên ............................................................ 11 Bài 3. Tìm số nguyên tố thứ N......................................................................... 12 Bài 4: Chú gấu Tommy và các bạn ................................................................. 14 Bài 5: Hoán đổi............................................................................................... 17 Bài 6: Thuyền trưởng Prime ........................................................................... 20 III. KẾT LUẬN ..................................................................................................... 25 TÀI LIỆU THAM KHẢO .................................................................................... 26 I. ĐẶT VẤN ĐỀ 1. Lí do chọn đề tài: Công tác tự học và tự nghiên cứu là một trong những hoạt động quan trọng của giáo viên nhằm đáp ứng yêu cầu dạy học, đặc biệt là trong công tác bồi dưỡng học sinh giỏi. Đối với việc bồi dưỡng học sinh giỏi môn Tin học, có khá nhiều chuyên đề, bài tập thường gặp trong các kỳ thi. Các bài toán về số học nói chung và số nguyên tố nói riêng là một trong những bài tập thường gặp đó. Trong một số bài toán, ta rất hay gặp các yêu cầu mà cần phải xác định được các số nguyên tố trong một phạm vi giới hạn nào đó như: xét tính nguyên tố, liệt kê các số nguyên tố, đếm các số nguyên tố,… Sàng nguyên tố Eratosthenes là một thuật toán hiệu quả để kiểm tra, liệt kê, đếm,… các số nguyên tố trong đoạn [1,N]. Tuy nhiên trong giới hạn thời gian 1 giây, nó chỉ thực sự hiệu quả khi N ≤ 10 . Một cải tiến làm cho sàng 7 Eratosthenes có thể hiệu quả khi N ≤ 108trong giới hạn thời gian 1 giây để áp dụng trong một số bài tập sẽ được trình bày trong sáng kiến này. 2. Mục đích của đề tài:
- Trình bày về sàng Eratosthenes và cách cải tiến sàng Eratosthenes để áp dụng giải một số bài toán liên quan. 3. Nhiệm vụ của đề tài: • Trình bày sàng Eratosthenes và cải tiến sàng Eratosthenes. • Một số bài tập áp dụng và hướng dẫn giải. 4. Giới hạn, phạm vi nghiên cứu của đề tài: Đề tài sáng kiến nghiên cứu các cải tiến sàng Eratosthenes và áp dụng giải một số bài toán trong chương trình bồi dưỡng học sinh giỏi Tin học tại trường THPT Thanh Chương 1. 1 II. NỘI DUNG 1. Định nghĩa số nguyên tố: Số nguyên tố là số tự nhiên lớn hơn 1 không phải là tích của hai số tự nhiên nhỏ hơn. Nói cách khác, số nguyên tố là những số chỉ có đúng hai ước số là 1 và chính nó. Các số tự nhiên lớn hơn 1 không phải là số nguyên tố được gọi là hợp số Ví dụ: Số 11 là số nguyên tố do chỉ có 2 ước là 1 và 11. Số 9 không phải là số nguyên tố do có 3 ước là 1, 3, 9. 2. Thuật toán Vét cạn (Brute Forces) Đây là thuật toán sử dụng kỹ thuật vét hết tất cả các số lẻ và kiểm tra tính nguyên tố của nó theo định nghĩa. Code minh họa
- #include using namespace std; void Bruce_forces(long limit) { long count = 1; bool isPrime = true; for (long i = 3; i
- không phải là số nguyên tố) các bội của k (k≤N2) 2 Khi giải thuật kết thúc (k > N ), tất các số chưa bị đánh dấu trong danh sách là các số nguyên tố cần tìm Code minh họa: bool prime[10000001]; void Era(int n) { memset(prime, true, n); for (int k=2; k*k
- N Số lượng Brute Force Eratosthenes SNT Độ phức tạp O((n√n)/4) O(nloglogn) 1000 168 0.002 0.001 10000 1229 0.003 0.001 100000 9592 0.01 0.004 1000000 78498 0.124 0.013 10000000 664579 3.109 0.205 100000000 5761455 86.715 2.915 1000000000 50847534 TLE 32.924 Nhìn vào bảng thống kê ta thấy: - V i n ≤ 106, chỉ cần thuật toán vét cạn thông thường ta có thể giải quyết tốt bài toán đã nêu. 7 - Với n = 10 , tất cả các thuật toán sàng nguyên tố đều làm tốt - Với n = 108, 109 tất cả các thuật toán đều không thực hiện tốt. Trong số đó, Sàng Eratosthenes là thuật toán cho kết quả tốt nhất, xấp xỉ 3s. 4. Cải tiến 1 Nhận xét: trừ số 2, tất cả các số chẵn đều không phải là số nguyên tố. Vì vậy ta sẽ không xét đến các số chẵn trong thuật toán, khi đó không gian lưu trữ giảm xuống còn n/2. Điều này sẽ làm giảm thời gian thực hiện thuật toán. Code minh họa: bool prime[10000001/2]; void Era1(int n){ memset(prime,true,n/2); for (long long i = 3; i < n; i += 2) { if (prime[i/2])//i la so nguyen to { for (long long j = i*i; j < n; j += 2*i) 4 prime[j/2] = false;
- } } } 5. Cải tiến 2 Nhận xét: các số chẵn (trừ số 2) và các số là bội của 2 hoặc 3 đều không phải là nguyên tố. Do đó, ta chỉ cần xét các số không phải là bội của 2 hoặc 3. Các số không phải là bội của 2 hoặc 3 sẽ có bước nhảy lần lượt là +2 và +4 bắt đầu từ 5. Cụ thể ta có: 5 (+2) 7 (+4) 11 (+2) 13 (+4) 17 ... Đây là các số có khả năng là số nguyên tố. Ta sẽ giảm không gian lưu trữ xuống còn n/3 vì vậy thời gian thực hiện thuật toán giảm xuống. Code minh họa: bool prime[10000001/3]; void Era2(int n){ memset(prime,true,n/3); for (int i = 5, k = 2; i< n; i += k, k = 6 - k) { if (prime[i/3])//i la so nguyen to { for (int j = i*i,v = k; j < n; j += v*i, v = 6 - v) prime[j/3] = false; } } } 6. Cải tiến 3 Để giảm bộ nhớ hơn, ta sử dụng xử lí bit để đánh dấu các số nguyên tố như sau: - Ta sẽ sử dụng phần tử prime[0] để đánh dấu các số từ 1 đến 32, phần tử prime[1] để đánh dấu các số từ 33 đến 64, và cứ thế tiếp tục… prime[0] prime[1] 10010000010001010001010001010101 11010100000100000100010100010011 32 31 64 63 34 332 1
- 5 - Các số chẵn (trừ 2) không phải là số nguyên tố, vì vậy ta không cần đánh dấu các số chẵn. Lúc này dùng prime[0] để đánh dấu các số 1, 3, 5, …, 63; prime[1] để đánh dấu các số 65, 67, …, 127;… prime[0] prime[1] 10010000010001010001010001010101 01010100000100000100010100010001 63 61 127 125 67 653 1 Với cách tổ chức đánh dấu như trên thì việc xác định một số M đước đánh dấu bởi bit nào trong phần tử nào thuộc mảng prime được xác định như sau: - Do mỗi phần tử chứa một đoạn giá trị là 64, ta thực hiện phép chia M/64 hay M>>6 (dịch phải 6 bit). Nghĩa là phần tử thứ prime[M>>6] chứa bit đánh dấu M. - Để biết được bit nào đánh dấu số M, do mỗi phần tử chứa một khoảng giá trị là 64, ứng với 32 bits, nên bit cần tìm là số dư khi chia M cho 64 (M%64) chia cho 2 (do không tính số chẵn). Để tăng tốc độ ta sử dụng phép toán trên bit thay cho phép toán %. Ta có (M%64)/2 = (M&63)>>1. - VD: M = 67, ta có M>>6 = 1, và (M&63)>>1 = 1. Nghĩa là số M được đánh dấu bởi bit thứ 1 trong phần tử prime[1]. Code minh họa: #define MAX 100000000 #define check(m) (prime[m>>6]&(11))) #define set(m) prime[m>>6]|=(11)) int prime[MAX>>6]; void Era3(){ for(int i=3;i*i
- 6 Kết quả sau cải tiến Thực nghiệm được thực hiện trên máy tính có cấu hình: Intel Core 2 (3.0 GHz), RAM 8GB, Windows 64 bit. Cho kết quả như sau: N Số Eratosthen Eratosthenes Eratosthenes lượng es (cải tiến (cải tiến2 ) (cải tiến 3) SNT 1) 1000 168 0.001 0 0.001 10000 1229 0.002 0.002 0.002 100000 9592 0.002 0.002 0.002 1000000 78498 0.008 0.007 0.006 10000000 664579 0.064 0.053 0.061 100000000 5761455 1.491 1.031 0.668 1000000000 50847534 17.118 11.731 8.860 Nhìn vào bảng thống kê ta thấy sau khi cải tiến đến lần 3, thuật toán Eratosthenes có thể giải bài toán với giới hạn 108rất tốt. Tuy nhiên, khi n = 109thì thuật toán vẫn còn khá chậm nhưng đã có sự cải tiến đáng kể. Trên các hệ thống chấm online thuật toán sẽ chạy nhanh hơn. 7. Một số bài toán ví dụ áp dụng Bài 1: Factor Cho bạn một số nguyên dương T là số test cần xử lý. T dòng tiếp theo là T số nguyên dương M, hãy phân tích M ra thành tích các thừa số nguyên tố. 5 7 Giới hạn là T
- FACTOR.INP FACTOR.OUT 2 3*5 15 2*3*5 30 7 Thuật toán: Ta có thể phân tích số M ra thừa số nguyên tố bằng thuật toán thông thường có độ phức tạp O(M) như sau: void factor(long M){ for(long i = 2; i*i
- hết. Từ nhận xét trên, ta sẽ dùng Sàng Eratosthenes để xác định số nguyên tố nhỏ nhất thỏa nhận xét trên trong thời gian O(1) int min_prime(){ for (long i = 2; i*i
- //------------------------------- int min_prime(){ for (long long i = 2; i*i
- //------------------------------ int main(){ process(); return 0; } Độ phức tạp: O(nlog(n)) 10 Bài 2. Tổng các số nguyên tố đầu tiên Cho một số nguyên dương N. Yêu cầu tính tổng của N số nguyên tố đầu tiên. Dữ liệu vào: cho trong tệp có cấu trúc: - Dòng đầu tiên chứa số T là số lượng bộ tests (1 ≤ T ≤ 103) - T dòng tiếp theo, mỗi dòng ch a một số N (1 ≤ N ≤ 106). Kết quả ra: ghi ra tệp gồm T dòng, mỗi dòng ghi một số tương ứng là tổng của N số nguyên tố đầu tiên. Ví dụ: Dữ liệu vào Kết quả ra 3 28 5 5 2 58 7 Hướng dẫn: Tương tự bài 2, giá trị của số nguyên tố thứ N có thể lên đến 8 10 . Vì vậy dùng sàng cải tiến kết hợp mảng tính trước tổng của N số nguyên tố đầu tiên. Code minh họa: #include using namespace std; #define MAX 100000000 #define check(n) (prime[n>>6]&(11))) #define set(n) prime[n>>6]|=(11)) int t,n;
- long long sum[1000001]; int prime[MAX>>6]; void Era3(){ for(int i=3;i*i
- Kết quả ra: Ghi ra tệp gồm T dòng, mỗi dòng ghi một số tương ứng là giá trị của số nguyên tố thứ N cho trong tệp dữ liệu vào. Ví dụ: Dữ liệu vào Kết quả ra 4 13 6 3 2 11 5 7 4 12 8 Hướng dẫn: Giá trị của số nguyên tố thứ N có thể lên đến 10 . Vì vậy dùng sàng cải tiến để tạo trước mảng chứa các số nguyên tố. Code minh họa: #include using namespace std; #define MAX 100000000 #define check(n) (prime[n>>6]&(11))) #define set(n) prime[n>>6]|=(11)) int pri[1000001],t,n; int prime[MAX>>6]; void Era3(){ for(int i=3;i*i
- if(!check(i)){ dem++; pri[dem] = i; } } int main(){ //freopen("","r",stdin); freopen("","w",stdout); Era3(); scanf("%d",&t); for(int i=1;i
- vấn. Ví dụ: TOMMY.INP TOMMY.OU T 6 9 5 5 7 10 14 15 7 3 2 10 0 3 12 44 Thời gian: 1s 14 Giải thích: 3 truy vấn trong test1 1. Truy vấn 1: l = 2, r = 11. Ta cần tính: f(2) + f(3) + f(5) + f(7) + f(11) = 2 + 1 + 4 + 2 + 0 = 9. 2. Truy vấn 2: l = 3, r = 12. Ta cần tính: f(3) + f(5) + f(7) + f(11) = 1 + 4 + 2 + 0 = 7. 3. Truy vấn 3: l = 4, r = 4 không có số nguyên tố. Hướng dẫn: Cách 1: O(m.n.y) với y lá số lượng số nguyên tố trong đoạn [l,r] B1) Đọc file và xác định giá trị c[i] là số lần xuất hiện của giá trị i trong dãy số. B2) 7 Dùng sàng Eratosthenes để xác định các số nguyên tố trong đoạn [1..10 ] B3) Với mỗi truy vấn trong m truy vấn, ta lần lượt xét từng số nguyên tố i trong đoạn [li,ri]. - Với mỗi số nguyên tố i, ta duyệt lại mảng x và đếm số lượng bội của i là f(i); - Tổng các f(i) chính là kết quả cần tìm. Cách 2: O(max(m,n).y) B1) Tương tự cách 1 B2) Dùng sàng số nguyên tố, kết hợp tính các giá trị f(i) (với i là số nguyên tố trong đoạn [1, 107) - Tính f(2)? f(2) = c[2]+ c[4] + c[6] + c[8],...
- - Tính f(5)? f(5) = c[5] + c[10]+ c[15] + c[20],... - Tính f(n)? f(n) = c[n] + c[2·n] + c[3·n] + c[4·n],... Ta thấy tư tưởng này rất giống với thuật toán sàng Eratosthenes. Vì vậy ta có thể dùng thuật toán sàng và chỉnh sửa lại. Kết quả tính sẽ được lưu trữ vào f[n] B3) Với mỗi truy vấn trong m truy vấn, ta lần lượt xét từng số nguyên tố i trong đoạn [li,ri]. Ta tính tổng các f(i) chính là kết quả cần tìm. Cách 3: O(max(m,n)) Để giải bài toán này ta cần giải quyết một số vấn đề sau: B1, 2) Tương tự cách 2 B3) Bây giờ ta cần tính tổng tiền tố S của mảng num. Với S[i] = f[1] + f[2] + …+f[i] B4) Sau khi tính tổng tiền tố xong, ta có thể tính toán tổng số lượng phần tử giữa l và r trong thời gian O(1), nghĩa là ta tính s[r] – s[l-1]. Bây giờ ta có thể đọc các truy vấn và trả lời chúng dễ dàng. Cần lưu ý là cận phải r có thể lớn hơn 107, vì vậy ta có thể giải r xuống chỉ còn 7 7. 10 thôi và tất cả các số được cho đều bé hơn hoặc bằng 10 15 Code #include using namespace std; #define MAX 10000001 int prime[MAX]; long c[MAX], f[MAX]; long long sum[MAX]; long t,n,m; //FILE * fi = freopen("tommy.inp","r",stdin); //FILE * fo = freopen("tommy.out", "w", stdout); ifstream fi ("tommy.inp"); ofstream fo ("tommy.out"); //--------------------------- int eratosthene(){ for(long long i=2;i*i
- prime[j]=true; } } } return 0; } //------------------------------- void process(){ fi>>n; for(long i = 1; i>t; ++c[t]; 16 } eratosthene(); for(long i = 2; i>m; long li,ri; for (long i = 1; i>li>>ri; if (ri>1E7) ri = 1E7; fo
- Bài 5: Hoán đổi Trong giờ giải lao, do lớp vừa học xong các kiến thức về số nguyên tố, nên lớp trưởng của John đã suy nghĩ ra một trò chơi về dãy số cũng khá thú vị. Trò chơi như sau: Cho một dãy số a[1], a[2], ..., a[n], gồm các số nguyên phân biệt từ 1 đến n. Nhiệm vụ là ta phải sắp xếp các số theo thứ tự tăng dần theo qui tắc sau (có thể áp dụng nhiều lần): 1. Chọn trong dãy số 2 chỉ số i, j (1 ≤ i
- Nhận xét: với mỗi số i ta đã tìm vị trí xa nhất thỏa yêu cầu để hoán đổi nên có thể thấy đây là thuật toán tốt. Thực tế cài đặt cho thấy số lần hoán đổi thỏa yêu cầu đề bài. Chi tiết thuật toán: 1. Khi đọc dãy số ta tiến hành lưu lại vị trí của từng số a[i] ban đầu là y[a[i]] = i 2. Xét từng số i = 1, 2, 3, …, n. Với mỗi số ta thực hiện nhiều lần các bước sau: a. Gọi j = y[i] là vị trí hiện tại của số i trong dãy số. Trong khi j>i (i chưa đúng chỗ), ta thực hiện tìm vị trí t thích hợp để hoán đổi giá trị i với t = i, i+1, i+2, … b. Khi tìm được vị trí t phù hợp, ta thực hiện đếm số lần hoán đổi và cập nhật vị trí như sau - y[a[t]] = j - y[a[j]] = t c. Hoán đổi a[t] và a[j] Code tham khảo: #include using namespace std; #define check(n) (prime[n>>6]&(11))) #define set(n) prime[n>>6]|=(11)) 18 #define MAX 100000000 long y[100000005],c=0,a[100000005],n,t,j; vector< pair < long , long > > v; int prime[MAX>>6]; //------------------- void eratos(){ for (long i=3;i*i
CÓ THỂ BẠN MUỐN DOWNLOAD
-
Sáng kiến kinh nghiệm THPT: Đổi mới phương pháp dạy häc môn TDTT cấp THPT
20 p | 362 | 67
-
Sáng kiến kinh nghiệm THPT: Một số biện pháp quản lý phòng máy tính trong nhà trường
29 p | 276 | 62
-
Sáng kiến kinh nghiệm THPT "Một số kinh nghiệm huấn luyện kết hợp với băng hình tập huấn trong nâng cao đội tuyển học sinh giỏi bộ môn GDQP - AN phần: Lý thuyết"Sáng kiến kinh nghiệm THPT "Một số kinh nghiệm huấn luyện kết hợp với băng hình tập huấn trong nâng cao đội tuyển học sinh giỏi bộ môn GDQP - AN phần: Lý thuyết"
14 p | 190 | 28
-
Sáng kiến kinh nghiệm THPT: Tăng cường hứng thú và tập trung của học sinh trong các tiết luyện tập môn Hóa học 11 THPT bằng các trò chơi
25 p | 26 | 12
-
Sáng kiến kinh nghiệm THPT: Ứng dụng classdojo – quản lý lớp, tạo tiết học hiệu quả, hỗ trợ kiểm tra đánh giá học sinh theo giáo dục STEM
43 p | 56 | 9
-
Sáng kiến kinh nghiệm THPT: Nâng cao kỹ năng giao tiếp bằng tiếng Anh
28 p | 35 | 8
-
Sáng kiến kinh nghiệm THPT: Phát triển tư duy lập trình và khắc phục sai lầm cho học sinh lớp 11 thông qua sử dụng cấu trúc rẽ nhánh
24 p | 31 | 7
-
Sáng kiến kinh nghiệm THPT: Kinh nghiệm giáo dục tư tưởng chính trị trong việc giảng dạy địa lí tự nhiên Việt Nam ở lớp 12
21 p | 45 | 7
-
Sáng kiến kinh nghiệm THPT: Nâng cao hiệu quả quản lý và giáo dục học sinh lớp 10 trong công tác chủ nhiệm ở trường THPT
37 p | 24 | 6
-
Sáng kiến kinh nghiệm THPT: Một số biện pháp nhằm nâng cao chất lượng tự học của học sinh THPT Thừa Lưu
26 p | 35 | 6
-
Sáng kiến kinh nghiệm THPT: Một số kinh nghiệm rèn kĩ năng viết đoạn văn nghị luận xã hội cho học sinh lớp 12 ở trường THPT Vĩnh Linh
20 p | 16 | 5
-
Sáng kiến kinh nghiệm THPT: Nghiên cứu dạy học phần Động cơ đốt trong - Công nghệ 11 theo định hướng giáo dục STEM
21 p | 54 | 5
-
Sáng kiến kinh nghiệm THPT: Hướng dẫn học sinh lớp 12 ôn tập môn Lịch Sử theo định hướng 5 bước 1 vấn đề, đáp ứng yêu cầu mới của kỳ thi THPT Quốc gia
29 p | 35 | 5
-
Sáng kiến kinh nghiệm THPT: Tích hợp kiến thức liên môn trong chuyên đề oxi- ozon – Hóa học 10- ban cơ bản
65 p | 47 | 4
-
Sáng kiến kinh nghiệm THPT: Giải pháp nâng cao chất lượng dạy, học Giáo Dục Quốc Phòng – An Ninh cho học sinh lớp 11 trường THPT Nguyễn Xuân Ôn
38 p | 42 | 4
-
Sáng kiến kinh nghiệm THPT: Xây dựng hiệu quả kế hoạch phong trào Nghiên cứu khoa học kỹ thuật trong học sinh tại Trường THPT Chuyên Thoại Ngọc Hầu
10 p | 28 | 3
-
Sáng kiến kinh nghiệm THPT: Một giải pháp nhằm nâng cao hiệu quả giảng dạy lý thuyết môn Giáo dục Quốc phòng, An ninh ở trường THPT
45 p | 46 | 3
-
Sáng kiến kinh nghiệm THPT: Một số giải pháp nhằm nâng cao chất lượng trong công tác bồi dưỡng học sinh giỏi môn Sinh học ở trường THPT
23 p | 24 | 3
Chịu trách nhiệm nội dung:
Nguyễn Công Hà - Giám đốc Công ty TNHH TÀI LIỆU TRỰC TUYẾN VI NA
LIÊN HỆ
Địa chỉ: P402, 54A Nơ Trang Long, Phường 14, Q.Bình Thạnh, TP.HCM
Hotline: 093 303 0098
Email: support@tailieu.vn