SÁCH CÁC KIẾN THỨC CƠ BẢN DÀNH CHO KỲ THI OLIMPIC TIN HỌC SINH VIÊN TOÀN QUỐC

45 2 0
SÁCH CÁC KIẾN THỨC CƠ BẢN DÀNH CHO KỲ THI OLIMPIC TIN HỌC SINH VIÊN TOÀN QUỐC

Đ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

SÁCH CÁC KIẾN THỨC CƠ BẢN DÀNH CHO KỲ THI OLIMPIC TIN HỌC SINH VIÊN TOÀN QUỐC QUYỂN TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN MỤC LỤC ĐÁNH GIÁ THUẬT TOÁN Lý cần đánh giá thuật toán Độ phức tạp thuật toán Các quy tắc xác định độ phức tạp Bài tập SỐ NGUYÊN Phép chia dư Số nguyên tố Phép chia hết Số phương Số Fibonacci Bài tập 12 MỘT SỐ BÀI TOÁN ỨNG DỤNG Ý TƯỞNG SÀNG NGUYÊN TỐ 14 Nhắc lại sàng nguyên tố 14 Ứng dụng 1:Tìm số ước số n 14 Ứng dụng 2:Tính tổng ước số n 15 Ứng dụng 3: Tính tổng tất thừa số nguyên tố 16 Ứng dụng 4:Tính tổng tất thừa số nguyên tố khác 16 Ứng dụng 5: Tính số lượng số nguyên dương nhỏ n nguyên tố với n 16 MỘT SỐ BÀI TOÁN KỸ THUẬT LẬP TRÌNH CƠ BẢN 18 PHƯƠNG PHÁP CHIA ĐỂ TRỊ 25 Khái niệm 25 Các bước tiếp cận xây dựng thuật toán chia để trị 25 Đánh giá phương pháp chia để trị 26 Một số toán minh họa 26 Kết luận 29 Bài tập 29 PHƯƠNG PHÁP THỬ VÀ SAI 30 Khái niệm 30 Mơ hình tốn 30 Đánh giá phương pháp 30 Các bước tiếp cận phương pháp thử sai 31 TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN PHƯƠNG PHÁP QUAY LUI(Backtracking) 34 Khái niệm 34 Thuật toán quay lui 34 Một số toán áp dụng 35 QUY HOẠCH ĐỘNG 37 Giới thiệu 37 Bài toán quy hoạch động 37 Phương pháp quy hoạch động 37 Một số toán áp dụng 38 PHÂN ĐOẠN SQRT(Sqrt decomposition) 43 Bài toán mở đầu 43 Thuật toán phân đoạn SQRT 43 Cài đặt 44 TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GỊN ĐÁNH GIÁ THUẬT TỐN Lý cần đánh giá thuật tốn - Xác định tính khả thi thuật toán độ lớn liệu: thời gian thực thi có chấp nhận, dung lượng nhớ sử dụng có phù hợp - So sánh thuật tốn giải tốn - Tiêu chí đánh giá thuật tốn  Tính đắn  Tính đơn giản  Dung lượng nhớ tiêu thụ  Thời gian thực thi - Thuật toán đánh giá dựa vào thời gian thực thi Thời gian thực thi phụ thuộc  Kích thước liệu (độ lớn liệu/kích thước tốn): số phần tử liệu cần xử lý độ lớn miền giá trị liệu xử lý  Trạng thái liệu  Tốc độ máy tính  Ngơn ngữ lập trình  Kỹ cài đặt - Thời gian thực thi đánh giá dựa số thao tác sơ cấp mà thuật toán thực hiện: phép toán logic, phép gán, phép toán số học Kí hiệu hàm đo thời gian 𝑇(𝑛), 𝑛 kích thước tốn Độ phức tạp thuật toán - Độ phức tạp thuật toán đánh giá dựa tỉ suất tăng (tốc độ tăng) hàm 𝑇(𝑛) 𝑛 tăng, kí hiệu độ phức tạp 𝑇(𝑛) = 𝑂(𝑓(𝑛)), 𝑓(𝑛) tỉ suất tăng 𝑛 - Ví dụ xét hàm thời gian 𝑇1 (𝑛) = 100 ∗ 𝑛 𝑇1 (𝑛) = 𝑛2 Khi 𝑛 đủ lớn (𝑛 > 100) 𝑇1 (𝑛) < 𝑇2 (𝑛) Ta thấy 𝑇1 (𝑛) có tốc độ tăng theo 𝑓(𝑛) = 𝑛, 𝑇1 (𝑛) có tốc độ tăng theo 𝑓(𝑛) = 𝑛2 Vậy độ phức tạp 𝑇1 (𝑛) = 𝑂(𝑛), 𝑇2 (𝑛) = 𝑂(𝑛2 ) - Xét thuật tốn tổng qt có hàm đo thời gian thực thi 𝑇(𝑛)  𝑓(𝑛) gọi độ phức tạp 𝑇(𝑛) tồn số dương 𝑐 𝑛0 cho 𝑇(𝑛) ≤ 𝑐 ∗ 𝑓(𝑛), ∀𝑛 ≥ 𝑛0  Ví dụ tính độ phức tạp thuật toán 𝑇(𝑛) = (𝑛 + 1)2 Chọn 𝑐 = 4, 𝑛0 = ta có 𝑇(𝑛) ≤ 𝑐 ∗ 𝑛2 , ∀𝑛 ≥ 𝑛0 Vậy độ phức tạp thuật toán 𝑂(𝑛2 ) - Các trường hợp đánh giá thuật toán  Xấu nhất: trường hợp thuật toán thực nhiều thao tác sơ cấp  Tốt nhất: trường hợp thuật toán thực thao tác sơ cấp  Trung bình: số thao tác sơ cấp trung bình - Độ phức tạp thuật toán đánh giá trường hợp xấu - Sự phân lớp biểu thức độ phức tạp  Những thuật tốn có độ phức tạp nhỏ 𝑂(𝑛3 ) cài đặt thực thi máy tính  Những thuật tốn có độ phức tạp đa thức 𝑂(2𝑛 ), 𝑂(𝑛!), 𝑂(𝑛𝑛 ) thực thi máy tính - Các hàm đánh giá độ phức tạp thơng dụng theo kích thước toán 𝑛 TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN STT Hàm đánh giá Dạng hàm Tính khả thi 𝑐 Hàm Khả thi 𝑙𝑜𝑔2 𝑛 Hàm logarit Khả thi 𝑛 Hàm tuyến tính Khả thi 𝑛 ∗ 𝑙𝑜𝑔2 𝑛 𝑛2 Hàm bậc Khả thi 𝑛3 Hàm bậc Khả thi 2𝑛 < 𝑛! < 𝑛𝑛 Đa thức Không khả thi Khả thi Các quy tắc xác định độ phức tạp a) Quy tắc bỏ hệ số - 𝑇(𝑛) = 𝑂(𝑐 ∗ 𝑓(𝑛)) = 𝑂(𝑓(𝑛)) với 𝑐 số b) Quy tắc tổng - Nếu thuật tốn phải thực thi thành phần có hàm thời gian tương ứng 𝑇1 (𝑛) = 𝑂(𝑓(𝑛)) 𝑇1 (𝑛) = 𝑂(𝑔(𝑛)) thời gian thực thi tồn 𝑇(𝑛) = 𝑇1 (𝑛) + 𝑇2 (𝑛) = 𝑂(𝑓(𝑛) + 𝑔(𝑛)) c) Quy tắc lấy max - 𝑇(𝑛) = 𝑂(𝑓(𝑛) + 𝑔(𝑛)) = 𝑂(max{𝑓(𝑛), 𝑔(𝑛)}) d) Quy tắc nhân - Nếu thuật tốn 𝑇1 có độ phức tạp 𝑇1 = 𝑂(𝑓(𝑛)) lồng thuật tốn 𝑇2 có độ phức tạp 𝑇2 = 𝑂(𝑔(𝑛)) độ phức tạp tồn 𝑇(𝑛) = 𝑂(𝑔(𝑛) ∗ 𝑓(𝑛)) Bài tập Cho số nguyên dương 𝑎, 𝑏 Viết hàm tính 𝑈𝐶𝐿𝑁(𝑎, 𝑏) Function UCLN(a, b: qword): qword; Var c: qword; Begin While (b > 0) Begin c := a mod b; a := b; b := c; End; Exit(a); End; Kiểm tra số nguyên dương 𝑛 có phải số nguyên tố -> xây dựng sàng nguyên tố Procedure CreateSieve; TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN Var i, j: longint; Begin Fillchar(Prime, sizeof(Prime), true); For i := to sqrt(maxN) if (Prime[i] = true) then begin j := i*i; while (j 0, tồn số nguyên q r (0 ≤ r < b) cho a = q.b + r Trong - q gọi phần nguyên a chia b kí hiệu q = a div b r gọi phần dư a chia b, kí hiệu r = a mod b Với x, y nguyên, n nguyên dương, tính chất phép mod - (x + y) mod n = ((x mod n) + (y mod n)) mod n -x mod n = (n-x) mod n (x.y) mod n = (x mod n)(y mod n) mod n xy mod n = (x mod n)y mod n Số nguyên tố Số nguyên dương p > gọi nguyên tố p chia hết cho Số ngun dương lớn nguyên tố gọi hợp số Thuật toán kiểm số nguyên dương n có phải số ngun tố Thuật tốn 1: độ phức tạp O(n) Function IsPrime(n: longint): boolean; Var i, dem: longint; Begin dem := 0; for i := to n if (n mod i = 0) then inc(dem); exit(dem = 2); End; Thuật toán 2: độ phức tạp 𝑂(√𝑛) Nhận xét: - Nếu a ước số dương n tồn b ước số dương n cho a*b = n (b = n div a) Khơng tính tổng qt, với số nguyên dương a, b cho a*b = n, giả sử a ≤ b ta có a*a ≤ a*b = n => a ≤ √𝑛 Do ta cần xét số từ đến √𝑛 để đếm số ước n, lần đếm ước Trường hợp a = b a*b = n, n số phương ước xem ước Function IsPrime(n: longint): boolean; Var i, dem, cann: longint; Begin TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN dem := 0; cann := trunc(sqrt(n)); for i := to cann if (n mod i = 0) then dem = dem + 2; if (cann*cann = n) then dem := dem – 1; exit(dem = 2); End; Thuật toán 3: Tạo sàng nguyên tố Tạo mảng chiều số mảng trùng với giá trị số nguyên tố vị trí Với mảng 𝑆𝑖𝑒𝑣𝑒 có kiểu boolean làm sàng nguyên tố, ta có 𝑆𝑖𝑒𝑣𝑒[𝑥] = 𝑡𝑟𝑢𝑒 𝑥 số nguyên tố, ngược lại 𝑆𝑖𝑒𝑣𝑒[𝑥] = 𝑓𝑎𝑙𝑠𝑒 Thuật toán tạo sàng var sieve: array[2 maxN] of boolean; procedure CreateSieve; begin fillchar(sieve, sizeof(sieve), true); for i := to trunc(sqrt(maxN)) if Sieve[i] then begin j := i*i; while (j Cho dãy gồm n số nguyên a1, a2, …, an ta có: - UCLN(a1, a2, …, an) = UCLN(a1, UCLN(a2, …, an)) Thuật tốn Euclide tìm ước chung lớn số nguyên dương a, b Function UCLN(a, b: longint): longint; Var c: longint; Begin While (b > 0) Begin c := a mod b; a := b; b := c; End; Exit(a); End; c) Bội chung nhỏ Cho số nguyên dương a, b Bội chung nhỏ a b số nguyên nhỏ chia hết cho a b, kí hiệu BCNN(a, b) BCNN(a, b) = a*b/UCLN(a, b) Số phương Số phương số bình phương số ngun Các số phương là: 1, 4, 9, 16, 25, … Một số tính chất: - Các chữ số tận số phương 0, 1, 4, 5, 6, Số phương khơng thể tận chữ số: 2, 3, 7, Phân tích thừa số nguyên tố số phương, số mũ thừa số nguyên tố số chẵn Số ước số phương ln số lẻ Số Fibonacci Dãy Fibonacci định nghĩa sau: 0, 𝑛=0 𝑛=1 𝐹𝑛 = { 1, 𝐹𝑛−1 + 𝐹𝑛−2 , 𝑛 ≥ với 𝑛 số nguyên dương Một số tính chất dãy Fibonacci TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN a) b) c) d) e) f) g) 2𝐹𝑛 = 𝐹𝑛+1 + 𝐹𝑛−2 𝐹1 + 𝐹2 + ⋯ + 𝐹𝑛 = 𝐹𝑛+2 − 𝐹1 + 𝐹3 + ⋯ + 𝐹2𝑛−1 = 𝐹2𝑛 𝐹2 + 𝐹4 + ⋯ + 𝐹2𝑛 = 𝐹2𝑛+1 − 𝐹12 + 𝐹22 + ⋯ + 𝐹𝑛2 = 𝐹𝑛 𝐹𝑛+1 𝐹2𝑛+1 = 𝐹𝑛 ∗ 𝐹𝑛 + 𝐹𝑛+1 ∗ 𝐹𝑛+1 𝐹2𝑛 = 𝐹𝑛 ∗ (𝐹𝑛+1 + 𝐹𝑛−1 ) Chứng minh tính chất b o Cách 1: dùng quy nạp Giả sử biểu thức với 𝑛 = 𝑘, nghĩa ta có 𝐹1 + 𝐹2 + ⋯ + 𝐹𝑘 = 𝐹𝑘+2 − Ta cần chứng minh 𝐹1 + 𝐹2 + ⋯ + 𝐹𝑘+1 = 𝐹𝑘+3 − Thật 𝐹1 + 𝐹2 + ⋯ + 𝐹𝑘 + 𝐹𝑘+1 = 𝐹𝑘+2 + 𝐹𝑘+1 − = 𝐹𝑘+3 − o Cách 2: ta có 𝐹1 + 𝐹2 = 𝐹3 𝐹2 + 𝐹3 = 𝐹4 … 𝐹𝑛 + 𝐹𝑛+1 = 𝐹𝑛+2 Cộng tất biểu thức ta có (𝐹1 + 𝐹2 + ⋯ + 𝐹𝑛 ) + (𝐹2 + 𝐹3 + ⋯ + 𝐹𝑛+1 ) = 𝐹3 + 𝐹4 + ⋯ + 𝐹𝑛+1 + 𝐹𝑛+2 (𝐹1 + 𝐹2 + ⋯ + 𝐹𝑛 ) + 𝐹2 = 𝐹𝑛+2 𝐹1 + 𝐹2 + ⋯ + 𝐹𝑛 = 𝐹𝑛+2 − 𝐹2 = 𝐹𝑛+2 − Chứng minh tính chất c 𝐹0 + 𝐹1 = 𝐹2 𝐹2 + 𝐹3 = 𝐹4 … 𝐹2𝑛−2 + 𝐹2𝑛−1 = 𝐹2𝑛 Cộng biểu thức ta có (𝐹0 + 𝐹2 + ⋯ + 𝐹2𝑛−2 ) + (𝐹1 + 𝐹3 + ⋯ + 𝐹2𝑛−1 ) = 𝐹2 + 𝐹4 + ⋯ + 𝐹2𝑛−2 + 𝐹2𝑛 𝐹1 + 𝐹3 + ⋯ + 𝐹2𝑛−1 = 𝐹2𝑛 Chứng minh tính chất e 10 TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN If Sum = S then inc(res); End; End; Exit(res); End; Độ phức tạp thuật toán 𝑂(𝑛3 ) Cách giải 2: tính sẵn tổng phần tử mảng a luu vào mảng sum Function CountSub: longint; Var l, r, res: longint; Begin Res := 0; For l := to n-3 For r := l+3 to n If (Sum[r]-Sum[l-1] = S) then inc(res); Exit(res); End; Độ phức tạp thuật toán 𝑂(𝑛2 ) Các bước tiếp cận phương pháp thử sai Mơ hình hóa nghiệm toán - Xác định số thành phần cấu hình (vector) nghiệm Xác định tập khả thành phần cấu hình (vector) ràng buộc thành phần Xây dựng thủ tục duyệt tất khả có nghiệm tốn Giảm thiểu số trường hợp duyệt Xây dựng hàm kiểm tra khả có thỏa u cầu nghiệm tốn Giảm thiểu chi phí kiểm tra Ví dụ: MẬT KHẨU AN TỒN Một xâu ký tự gọi mật “an tồn” xâu có độ dài xâu chứa chữ in hoa (‘𝐴’ ’𝑍’), chữ thường (‘𝑎’ ’𝑧’), chữ số (‘0’ ’9’) Ví dụ, ‘𝑎1𝐵2𝐶3’, ‘𝑡𝑖𝑛𝐻𝑜𝑐6’ hai mật “an tồn”, cịn ‘𝑎1𝐵2𝐶’, ’𝑎1𝑏2𝑐3’, ‘𝐴1𝐵2𝐶3’ ‘𝑡𝑖𝑛𝐻𝑜𝑐’ khơng phải mật “an tồn” 31 TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GỊN Một lần, Bình nhìn thấy xâu 𝑆, gồm loại ký tự: chữ in hoa, chữ thường chữ số Bình muốn tự kiểm tra khả đoán nhận mật cách đếm xem có cặp số (𝑖, 𝑗) thỏa mãn điều kiện: ≤ 𝑖 < 𝑗 ≤ 𝑙𝑒𝑛𝑔𝑡ℎ(𝑆) xâu gồm ký tự liên tiếp từ 𝑖 đến 𝑗 𝑆 mật “an toàn” Yêu cầu: Cho xâu 𝑆, tính số lượng cặp số (𝑖, 𝑗) thỏa mãn điều kiện nêu Dữ liệu: vào từ tập tin văn PASSWORD.INP xâu 𝑆 có độ dài khơng q 106 Kết quả: ghi tập tin văn PASSWORD.OUT số lượng cặp số (𝑖, 𝑗) tính Ví dụ: PASSWORD.INP PASSWORD.OUT abc3456789PQ PASSWORD.INP PASSWORD.OUT abc123 Phân tích - Chuỗi xâu 𝑆 mơ hình hóa vector (𝑙, 𝑟) Miền giá trị 𝑙, 𝑟 ∈ [1, |𝑆|] Ràng buộc: từ vị trí 𝑙 đến 𝑟 phải thỏa tất điều kiện sau o Có chứa kí tự hoa o Có chứa kí tự thường o Có kí tự số o 𝑙−𝑟 ≥5 Cách giải 1: Function Count: longint; Var l, r, Res, n: longint; Begin Res := 0; n := length(S); For l := to n-5 For r := l+5 to n 32 TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN For i := l to r If (S[i] >= ‘A’) and (S[i] = ‘a’) and (S[i] = ‘0’) and (S[i] max) then max := L[j]; L[i] := max + 1; End; End; Truy vết: - Để tìm phần tử dãy tăng ta cần tổ chức thêm mảng Prev[i] cho biết số phần tử nằm trước a[i] dãy tăng dài Cài đặt hoàn chỉnh: Procedure DP; Var i, j, max: longint; Begin L[0] := 0; //L[1] := 1; For i := to n Begin vtmax := 0; For j := to i-1 If (a[j] < a[i]) and (L[j] > L[vtmax]) then vtmax := j; L[i] := L[vtmax] + 1; Prev[i] := vtmax; End; End; 39 TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN Cài đặt truy vết tìm phần tử thuộc dãy tăng dài Procedure Trace; Var i, max: longint; Begin max := 1; For i := to n If (L[i] > L[max]) then max := i; m := 0; While (max > 0) Begin Inc(m); Res[m] := max; max := Prev[max]; End; End; Cải tiến: - Gọi 𝑖𝑑(𝑙𝑒𝑛) số phần tử cuối nhỏ dãy tăng có đội dài 𝑙𝑒𝑛, nghĩa 𝑎[𝑖𝑑(𝑙𝑒𝑛)] phần tử cuối có giá trị nhỏ số dãy tăng có chiều dài 𝑙𝑒𝑛 nhận 𝑎[𝑖𝑑(𝑙𝑒𝑛)] phần tử cuối Ví dụ: - - A 10 15 i id len Với phần tử a[i], ta tìm dãy tăng (có độ dài len) phần tử nhỏ lớn a[i] thay phần tử a[i] Vì phần tử mảng id có thứ tự tăng nên ta chặt nhị phân để tìm vị trí m mảng id cho a[id[m]] nhỏ a[id[m]] > a[i] Độ phức tạp thuật toán 𝑂(𝑛𝑙𝑜𝑔𝑛) Cài đặt: Function BinSearch(x, l, r: longint): longint; Var m: longint; Begin While (l < r) Begin 40 TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN m := (l + r) div 2; if (a[id[m]] < x) then l := m+1 else r := m; End; Exit((l+r) div 2); End; Procedure DP; Var i, m: longint; Begin id[1] := 1; len := 1; For i := to n If (a[i] < a[id[1]]) then id[1] := i Else If (a[i] > a[id[len]]) then Begin Inc(len); id[len] := i; End Else //if (a[i] nSegs) then pos := nSegs; //nSegs: số đoạn left := (pos – 1)*segL + 1; End; Procedure Decompose; Var i, pos, left: longint; Begin For i := to n Begin GetSeg(i, pos, left); //xác định thứ tự đoạn vị trí i If (pos = left) or (a[i] > MaxSeg[pos]) then MaxSeg[pos] := a[i]; End; End; Cài đặt hàm truy vấn tìm giá trị lớn phần tử từ vị trí 𝑙 đến vị trí 𝑟 Function MaxArr(var a: larr; l, r: longint): longint; Var i, max: longint; Begin max := a[l]; For i := l+1 to r If (a[i] > max) then max := a[i]; Exit(max); End; 44 TIẾN SĨ ĐÀO DUY NAM - TRƯỜNG CAO ĐẲNG SÀI GÒN Function Query(l, r: longint): longint; Var u, v, lu, ru, lv, res: longint; Begin GetSeg(l, u, lu); //tìm thứ tự đoạn l, lu: vị trí đầu đoạn u GetSeg(r, v, lv); //tìm thứ tự đoạn r, lv: vị trí đầu đoạn v If (u = v) then exit(MaxArr(a, l, r)); //nếu l,r thuộc đoạn ru := lu + segL – 1; //vị trí cuối đoạn u res := MaxArr(a, l, ru); if (u+1

Ngày đăng: 21/06/2022, 12:19

Tài liệu cùng người dùng

Tài liệu liên quan