# Toán học trong Tin học Bài viết này được viết theo đề nghị của một bạn cao **1,4m** (đã làm tròn xuống đến chữ số thập phân đầu tiên) trong lớp 10A5 LQĐ. Những phần trong bài viết này được sắp xếp theo độ khó tăng dần và các phần nằm gần nhau không nhất thiết phải liên quan đến nhau. Trong bài viết này, các mục từ $1$ đến $5$ là các chuyên đề dành cho khối THCS, các mục $6$ và $7$ là các chuyên đề dành cho khối THPT. Nguồn bài tập: https://lqdoj.edu.vn và https://lequydon.ntucoder.net (trang cũ của https://lqdoj.vn). ## 1. Ước và bội. Số nguyên tố. ### Ước và bội của một số, Số nguyên tố. #### Định nghĩa **Phép chia hết:** Khi phép chia số tự nhiên $a$ cho số tự nhiên $b$ cho số dư bằng 0, ta gọi đó là phép chia hết, và $a$ chia hết cho $b$, ký hiệu $a \vdots b$. **Ước và bội của một số:** Nếu $a$ chia hết cho $b$ thì ta nói $a$ là bội của $b$, còn $b$ là ước của $a$. ***Lưu ý:*** Đôi khi ta sẽ bắt gặp một số người viết $a|b$, có nghĩa là $b$ **chia hết cho** $a$ hay $a$ **chia hết** ~~cho~~ $b$. **Số nguyên tố:** Là số tự nhiên lớn hơn 1 và chỉ có hai ước là một và chính nó. Một số tự nhiên $n$ lớn hơn 1 luôn được viết dưới dạng tích các số nguyên tố $p_1*p_2*...*p_k$. Các ước của $n$ sẽ là tích của 0, 1 hoặc nhiều số nguyên tố trong dãy $p_1, p_2, ..., p_k$. **Ước chung lớn nhất:** Là số tự nhiên lớn nhất mà cả hai (hoặc nhiều) số cùng chia hết. Ước chung lớn nhất của $k$ số $p_1, p_2, ..., p_k$ được ký hiệu là $GCD(p_1, p_2, ..., p_k)$. **Bội chung nhỏ nhất:** Là số tự nhiên nhỏ nhất mà chia hết cho cả hai (hoặc nhiều) số. Bội chung nhỏ nhất của $k$ số $p_1, p_2, ..., p_k$ được ký hiệu là $LCM(p_1, p_2, ..., p_k)$. #### Tính chất 1. Mọi ước chung của hai số đều là ước của ước chung lớn nhất. Mọi bội chung của hai số đều là bội của bội chung nhỏ nhất. 2. $GCD(a, b, c) = GCD(GCD(a, b), c)$, $LCM(a, b, c) = LCM(LCM(a, b), c)$. 3. $GCD(a, b) = GCD(a+kb, b) = GCD(a-mb, b)$. ### Phân tích thừa số nguyên tố Một số $n \ge 2$ luôn có thể được viết dưới dạng $p_1^{k_1}*p_2^{k_2}*\dots*p_x^{k_x}$ với $p_1, p_2, \dots p_x$ là các số nguyên tố phân biệt. Việc viết $n$ thành tích của các lũy thừa nguyên tố như trên được gọi là phân tích thừa số nguyên tố. **Đặc biệt: mỗi số $n$ có không quá một thừa số nguyên tố không nhỏ hơn $\sqrt{n}$.** #### Một số công thức liên quan đến việc phân tich thừa số nguyên tố 1. Tính số ước của $n$: $$C=(k_1+1)(k_2+1)\dots(k_x+1)$$ 2. Tổng các ước của $n$: $$S=\frac{p_1^{k_1+1}-1}{p_1-1}*\frac{p_2^{k_2+1}-1}{p_2-1}*\dots*\frac{p_x^{k_x+1}-1}{p_x-1}$$ 3. Tích các ước của $n$: $$P=n^{\frac{C}2}$$ (Lưu ý: $n^{\frac{1}2}=\sqrt{n}$) ### Số mũ đúng Ở phần trên, các số $k_1$, $k_2$, ..., $k_x$ được gọi là các số mũ đúng của các số nguyên tố $p_1$, $p_2$, ..., $p_x$ với số $n$. Nói rộng ra, một số $t$ được gọi là số mũ đúng của $n$ với số nguyên tố $p$, ký hiệu là $V_p(n)$ khi và chỉ khi $n$ chia hết cho $p^t$ và không chia hết cho $p^{t+1}$. #### Một số tính chất về số mũ đúng: 1. $x$ là số chính phương $\Leftrightarrow$ $V_p(x)\vdots2$ $\forall p$. 2. $V_p(GCD(a, b)) = min(V_p(a), V_p(b))$ $\forall p$ 3. $V_p(LCM(a, b)) = max(V_p(a), V_p(b))$ $\forall p$ 4. $a\vdots b$ $\Leftrightarrow$ $V_p(a) \ge V_p(b)$ $\forall p$. 5. $V_p(n!)=[\frac{n}p]+[\frac{n}{p^2}]+...$ ### Hai số nguyên tố cùng nhau, Phi hàm Euler #### Hai số nguyên tố cùng nhau Hai số nguyên tố cùng nhau là hai số có ước chung lớn nhất bằng 1. ##### Tính chất Cho hai số $a$ và $b$ nguyên tố cùng nhau 1. Nếu $p$ là ước của $a$ thì $b$ không chia hết cho $p$ ($p$ có thể là số nguyên tố hoặc không). 2. Nếu $a*k$ chia hết cho $b$ thì $k$ chia hết cho $b$. 3. $kb+a$ nguyên tố cùng nhau với $b$. 4. $a^m$ nguyên tố cùng nhau với $b^n$. #### Phi hàm Euler Ta ký hiệu $\varphi(n)$ là số lượng số nguyên tố cùng nhau với $n$ mà nhỏ hơn $n$. ##### Tính chất 1. $\varphi(m)*\varphi(n)\le\varphi(m*n)$. Dấu bằng xảy ra khi và chỉ khi $m$ và $n$ nguyên tố cùng nhau. 2. $\varphi(p^k)=p^{k-1}*(p-1)=p^k*\frac{p-1}{p}$ với $p$ là số nguyên tố. 3. Từ 1 và 2 ta tính được công thức: $\varphi(n)=n(1-\frac{1}{p_1})(1-\frac{1}{p_2})...(1-\frac{1}{p_k})$ với $p_1, p_2, ..., p_k$ là các ước nguyên tố của $n$ ### Luyện tập 1. [Ước số chung](https://lqdoj.edu.vn/problem/w06scr) 2. [FACTOR](https://lqdoj.edu.vn/problem/factor02004) 3. [Bội chính phương (Tin học trẻ quốc gia 2020)](https://lqdoj.edu.vn/problem/sqrmul) 4. [Số chính phương](https://lqdoj.edu.vn/problem/1819socp) ## 2. Phép đồng dư. Nhân và lũy thừa Ấn Độ ### Định nghĩa đồng dư Ta nói $a$ đồng dư với $b$ trong modulo $r$ khi và chỉ khi $a-b\vdots r$, hay nói cách khác là $a$ và $b$ có cùng số dư khi chia cho $r$. Ký hiệu: $a\equiv b (mod r)$. ### Tính chất của phép đồng dư Cho hai số $a$, $b$ đồng dư với nhau trong modulo $r$. Khi đó: 1. $a+c\equiv b+c (modr)$ 2. $ac \equiv bc (modr)$ 3. $a^c\equiv b^c (modr)$ 4. Nếu tồn tại hai số $m\equiv n(modr)$ thì $am\equiv bn(modr)$. 5. Nếu $b\equiv c(modr)$ thì $a\equiv b\equiv c(modr)$. 6. $ac\equiv bc(modr), GCD(c, r) = 1\Rightarrow a\equiv b(modr)$ ### Nhân và lũy thừa Án Độ #### Bài toán Kiểu dữ liệu `long long` trong ngôn ngữ lập trình `C++` chỉ cho phép lưu trữ một số có giá trị không vượt quá $2^{64}$ (khoảng $1,8*10^{19}$). Vậy làm cách nào để tính giá trị của phép tính $a*b$ $mod$ $c$ trong `C++`, với $a, b, c \le 10^{18}$? #### Hưởng giải quyết Ta có thể chia nhỏ số $b$ để chuyển phép nhân hai số lớn thành phép nhân đôi và phép cộng. Cụ thể như sau: 1. Cần tính $a*b$ $mod$ $c$. 2. Nếu $b=1$, trả về $a$. 3. Ngược lại, đặt $t = [\frac{b}2]$. 4. Quay lại bước 1, lấy kết quả phép tính $a * t$ $mod$ $c$. Đặt kết quả đó là $p$. 5. Nếu $b$ chẵn thì trả về $p + p$ $mod$ $c$. 6. Ngược lại thì trả về $p + p + a$ $mod$ $c$. Quy trình hoạt động của thuật toán trên với $a=15$, $b=5$, $c=18$: - $(15*5)mod18=...$ - $(15*2)mod18=...$ - $(15*1)mod18=15$ - $(15*2)mod18=(15+15)mod18=12$ - $(15*5)mod18=(12+12+15)mod18=3$ - Kết quả: $3$. Tương tự với phép nhân Ấn Độ, phép lũy thừa chỉ có một điểm khác biệt là thay đổi dấu $+$ thành dấu $*$ và thay dấu $*$ thành dấu lũy thừa. ### Định lý Fermat nhỏ, Định lý Euler #### Định lý Fermat nhỏ Định lý Fermat nhỏ được phát biểu như sau: Cho $p$ là một số nguyên tố và $a$ không chia hết cho $p$. Khi đó $a^{p-1}\equiv 1(modp)$. #### Định lý Euler Định lý Euler được phát biểu như sau: Cho $a$ và $p$ là hai số nguyên tố cùng nhau. Khi đó $a^{\varphi(p)}\equiv 1(modp)$. Có thể thấy định lý Fermat nhỏ là một trường hợp của đinh lý Euler, nhưng với $p$ là số nguyên tố thì $p - 1$ là số nguyên dương $i$ nhỏ nhất thỏa mãn $a^i\equiv 1(modp)$, trong khi đó định lý Euler thì không đảm bảo điều này. ### Luyện tập 1. [POWER](https://lqdoj.edu.vn/problem/power) 2. [Lũy thừa mod](https://lqdoj.edu.vn/problem/powmodulo) 3. [Module 4](https://lqdoj.edu.vn/problem/mod4) ## 3. Dãy số Fibonacci Dãy số Fibonacci được lập theo quy tắc sau * $F_0=F_1=1$ * $F_i=F_{i-1}+F_{i-2}$ ### Tính nhanh dãy số Fibonacci Xét một số tự nhiên $i$. Đặt $a=F_i$, $b=F_{i+1}$. Ta có nhận xét sau: Trường hợp cơ bản: * $F_{i+2}=a+b=F_0*a+F_1*b$ * $F_{i+3}=b+(a+b)=F_1*a+F_2*b$ * $F_{i+4}=F_1*a+F_2*b+F_0*a+F_1*b = F_2*a+F_3*b$ Tiếp tục thực hiện quy nạp ta được: * $F_{i+k}=F_{i+k-2}+F_{i+k-1}=(F_{k-4}+F_{k-3})*a+(F_{k-3}+F_{k-2})*b=F_{k-2}*a+F_{k-1}*b$ Từ đó suy ra: * $F_{2i+1}=F_{i-1}*a+F_i*b=(b-a)*a+ab=2ab-a^2$ * $F_{2i+2}=F_i*a+F_{i+1}*b=a*a+b*b=a^2+b^2$ Từ nhận xét này ta có thể chuyển bài toán tính $F_n$ thành tính $F_n$ và $F_{n-1}$, sau đó sẽ đưa về tính $F_{\frac{n-1}2}$ và $F_{\frac{n-1}2+1}$ với $n$ lẻ (hoặc $F_{\frac{n}2}$ và $F_{\frac{n}2+1}$ nếu $n$ chẵn). ### Luyện tâp 1. [Fibo cơ bản](https://lqdoj.edu.vn/problem/fibo01) 2. [Lát gạch](https://lqdoj.edu.vn/problem/latgach4) ## 4. Phương trình bậc nhất hai ẩn và giải thuật Eucilid mở rộng ### Phương trình bậc nhất hai ẩn Phương trình có dạng $ax+by=c$, $x, y \in R$ được gọi là phương trình bậc nhất hai ẩn. Phương trình bậc nhất hai ẩn có vô số nghiệm thực với $a, b$ khác 0 hoặc $a=b=c=0$, có một nghiệm thực duy nhất khi $a$ hoặc $b$ bằng 0, và vô nghiệm với $a = b = 0$ và $c$ khác 0. ### Phương trình Diophantine Phương trình bậc nhất hai ân $ax+by=c$ với $x, y \in Z$ được gọi là phương trình Diophantine. **Nhận xét:** Nếu $(x_0, y_0)$ là một cặp nghiệm của phương trình thì $(x_0+ka, y_0-kb)$ cũng là một cặp nghiệm của phương trình. **Điều kiện có nghiệm:** $c\vdots GCD(a, b)$ ### Giải thuật Eucilid Giải thuật Eucilid dùng để tìm kiếm ước chung lớn nhất của hai số $a$ và $b$. Thuật toán này được minh họa như hình dưới đây <img src="https://cdn.ucode.vn/uploads/24630/upload/dgDmBgqg.gif" class="element-center content-img width-40 tablet-width-40 mobile-width-40" /> Giải thuật Eucilid dựa trên hai công thức: $$GCD(a, b)=GCD(b, a-kb)$$ và$$GCD(a,0)=a$$ ### Tìm một nghiệm của phương trình Diophantine - Giải thuật Eucilid mở rộng #### Bài toán Hãy tìm một cặp nghiệm nguyên $(x, y)$ của phương trình $ax+by=c$. Dữ liệu đảm bảo phương trình có nghiệm. ##### Giải quyết **Trường hợp đặc biệt:** $b=0$: trả về $x=\frac{c}{a}$, $y$ là một giá trị bất kỳ. Với $a=0$ thì ngược lại. **Biến đổi phương trình:** Đặt $k=[\frac{a}{b}]$, $r = a-kb$. Khi này $a = kb+r$. Khi này ta thay $kb+r$ vào $a$ ta được:$$(kb+r)x+by=c$$ Khai triển ra ta được: $$kbx+rx+by=c$$ Nhóm hạng tử cuối vào hạng tử đầu ta được: $$b(kx+y)+rx=c$$ Đặt $x'=kx+y$, $y'=x$. Lúc này ta sẽ giải phương trình $bx'+ry'=c$ như phương trình ban đầu. Lặp lại quá trình này đến khi phương trình về dạng đặc biệt, sau đó ta sẽ truy ngược về để tìm $x$ và $y$. Cụ thể, sau khi có được hai số $x'$, $y'$, ta sẽ thấy ngay $x=y'$ và $y=x'-ky'$. ##### Ví dụ minh họa Tìm một nghiệm nguyên của phương trình $15x+2y=8$ Ta có $k_0=[\frac{15}2]=7$ và $r_0=15-7*2=1$. Ta viết lại phương trình: $$2(7x+y)+x=8$$ Đặt $x_1=7x+y$, $y_1=x$, ta có phương trình mới: $$2x_1+y_1=8$$ Ta tính được $k_1=[\frac{2}1]=2$ và $r_1=2-2*1=0$. Ta viết lại phương trình: $$(y_1+2x_1)+0x_1=8$$ Đặt $x_2=y_1+2x_1$, $y_2=x_1$, ta có phương trình mới: $$x_2+0y_2=8$$ Lúc này ta tính được $x_2 = 8$. Ta sẽ gán cho $y_2$ một giá trị bất kỳ, ví dụ $1$. Ta có $x_1=y_2=1\Rightarrow y_1=x_2-k_1*y_2=8-2*1=6$. Ta có $x=y_1=6\Rightarrow y=x_1-k_0*y_1=1-7*6=-41$. Vậy $(x, y)=(6, -41)$ là một cặp nghiệm của phương trình. Thử lại: $15*6+(-41)*2=8$, đúng. Thuật toán được mô tả ở trên chính là giải thuật Eucilid mở rộng. ##### Code mẫu (C++), dữ liệu vào đảm bảo phương trình có nghiệm ```cpp=1 pair<long long, long long> ExtendedEucilid(long long a, long long b, long long c) { if(b == 0) return {c / a, 0}; long long k = a / b, r = a - k * b; pair<long long, long long> t = ExtendedEucilid(b, r, c); long long x_ = t.first, y_ = t.second; long long x = y_, y = x_ - k * y_; return {x, y}; } ``` ### Nghịch đảo modulo Một số y được gọi là nghịch đảo của số $x$ trong modulo $m$ khi và chỉ khi $xy\equiv1(modm)$. Số $y$ được ký hiệu là $x^{-1}$ trong tập modulo $m$. Ta có $\frac{a}{x}\ \%\ m=a*\frac{1}{x}\%\ m=a*x^{-1}\ \%\ m=ay\ \%\ m$. Một số nguyên $x$ không có nghịch đảo trong tập modulo $m$ khi $GCD(x, m)>1$ Để tìm được số $y$, ta sẽ giải phương trình bậc nhất hai ẩn $xu+mv=1$, sau đó tìm số nguyên dương nhỏ nhất đồng dư với $u$ trong modulo $m$. ### Luyện tập 1. [Phương trình](https://lqdoj.edu.vn/problem/inteqn) 2. [LONG LONG](https://lqdoj.edu.vn/problem/longlong) 3. [Phương trình Diophantine](https://lqdoj.edu.vn/problem/diophantine) 4. [Hàn tín điểm binh](https://lqdoj.edu.vn/problem/hantin) ## 5. Hoán vị, chỉnh hợp, tổ hợp Cho $n$ viên kẹo được đánh số từ 1 đến $n$. ### Hoán vị #### Bài toán: Hãy đếm số cách sắp xếp $n$ viên kẹo đã cho theo một thứ tự bất kỳ. ##### Giải: Tưởng tượng ta đặt một chiếc khay gồm $n$ ô xếp liền nhau, ở mỗi ô ta bỏ một viên kẹo. Vậy số cách bỏ các viên kẹo vào khay sẽ là số cách sắp xếp của $n$ viên kẹo. - Để chọn một viên kẹo bỏ vào ô đầu tiên ta có $n$ sự lựa chọn. - Để chọn một viên kẹo bỏ vào ô thứ hai ta có $n - 1$ sự lựa chọn (vì đã loại trừ viên kẹo bỏ vào ô thứ nhất). - ... - Để chọn một viên kẹo bỏ vào ô thứ $i$ ta có $n - i + 1$ sự lựa chọn. - ... - Để chọn một viên kẹo bỏ vào ô thứ $n$ ta chỉ có một sự lựa chọn. Vậy tổng số cách chọn là: $n*(n-1)*...*1 = n!$. Số cách chọn này là số hoán vị của $n$, ký hiệu là $P_n$ hay $P(n)$. Vậy $P_n = P(n) = n!$. ### Chỉnh hợp #### Bài toán: Hãy đếm số cách chọn ra $k$ viên kẹo ($k \le n$). Hai cách chọn được tính là khác nhau khi tồn tại một số $i$ sao cho viên kẹo vị trí $i$ của cách chọn này khác với viên kẹo ở vị trí $i$ của cách chọn kia. Lưu ý: Hai cách chọn $(1, 2)$ và $(2, 1)$ được coi là **khác nhau**. ##### Giải: Tương tự như cách giải của hoán vị, nhưng ở lần này chiếc khay chỉ có $k$ ngăn. Do đó số cách chọn sẽ là: $n*(n-1)*...*(n-k+1)=\frac{n*(n-1)*...*1}{(n-k)*...*1}=\frac{n!}{k!}$ Số cách chọn này gọi là chỉnh hợp chập $k$ của $n$, ký hiệu là $A^k_n$ hay $A(k, n)$. Vậy $A^k_n = A(k, n) = \frac{n!}{(n-k)!}$ ### Tổ hợp #### Bài toán: Hãy đếm số cách chọn ra $k$ viên kẹo ($k \le n$). Hai cách chọn được tính là khác nhau khi ở cách chọn này có một viên kẹo không nằm trong cách chọn kia. Lưu ý: Hai cách chọn $(1, 2)$ và $(2, 1)$ được coi là **giống nhau**. ##### Giải Để tránh các cách chọn $(1, 2)$ và $(2, 1)$ bị lặp lại, ta chỉ nhận các cách chọn mà các viên kẹo được sắp xếp theo thứ tự tăng dần. Để ý rằng với một cách chọn $(a_1, a_2, ..., a_k)$, ta sẽ có $P_k$ cách sắp xếp lại các viên kẹo đấy. Nói cách khác, cứ $P_k$ cách chọn $k$ viên trong $n$ viên kẹo ở chỉnh hợp, ta chỉ nhận một cách. Vậy số cách chọn được nhận là: $\frac{A^k_n}{P_k}=\frac{n!}{(n-k)!*k!}$ Số cách chọn một tập hợp gồm $k$ viên kẹo ($k$ số) trong $n$ viên kẹo ($n$ số) như trong bài toán được gọi là tổ hợp chập $k$ của $n$, ký hiệu là $C^k_n$ hay $C(n, k)$. Vậy $C^k_n = C(k, n) = \frac{n!}{(n-k)! * k!}$ ### Tam giác Pascal và nhận xét #### Tam giác Pascal ![](https://i.imgur.com/PoHJDBq.gif) Tam giác Pascal là một mảng tam giác như hình trên, với hai cạnh bên là các số 1, và số trong mỗi ô là tổng của hai ô ở trên gần nó nhất. Tam giác này có thể mở rộng xuống đến vô cùng. Đánh dấu các hàng của tam giác Pascal bắt đầu từ 0 từ trên xuống dưới, các cột của tam giác Pascal bắt đầu từ 0 từ trái sang phải, ta có nhận xét đầu tiên: số ở hàng $i$ cột $j$ của tam giác Pascal có giá trị đúng bằng $C^j_i$ (Các bạn có thể tự chứng minh bằng quy nạp). Ngoài ra, các bạn có thê thấy tổng các số ở hàng dưới gâp đôi hàng trên (các bạn có thể chứng minh) mà tổng các số hàng trên cùng là 1 ($2^0$), do đó tổng các số ở hàng thứ $n$ sẽ là $2^n$. Rút ra công thức, ta được $C^1_n + C^2_n + ... + C^n_n = 2^n$. Ta nhận thấy tam giác Pascal có tính đối xứng trục, hay nói cách khác $C^k_n=C^{n-k}_n$. Ta cũng có thể tìm được cách chứng minh công thức sau trên tam giác Pascal: $C^0_i + C^1_{i-1} + ... + C^{[\frac{i}{2}]}_{n-[\frac{i}{2}]}=F_i$, với $F_i$ là số Fibonacci thứ $i$. ### Một số bài toán tổ hợp: **Bài toán 1:** Có bao nhiêu cách để đi từ đỉnh trái trên đến đỉnh phải dưới của hình chữ nhật $n \times k$, với mỗi bước chỉ được đi sang phải một bước hoặc đi xuống dưới một bước? Ký hiệu R là thao tác đi sang bên phải, D là thao tác đi xuống dưới. Xét dãy gồm $n+k$ chữ R. Ta cần chuyên $k$ chữ R thành các chứ D để biểu thị một đường đi từ đỉnh trái trên đến đỉnh phải dưới của hình chữ nhật. Vậy ta có $C^k_{n+k}$ cách chọn $k$ chữ R, ứng với đó là $C^k_{n+k}$ đường đi. **Bài toán 2:** Có bao nhiêu bộ $k$ số nguyên dương có tổng bằng $n$ ($k\le n$)? Đặt một dãy gồm $n$ số 1, ở giữa hai số 1 liên tiếp đặt một số 0, vậy ta có $n-1$ số 0. Ta cần chọn ra $k-1$ số 0 để đặt các "vách ngăn" chia các số 1 thành $k$ phần. Vậy ta có số cách chọn là: $C^{k-1}_{n-1}$. Với ý tưởng của bài toán 2, ta cũng có thể thấy được có $C^{k-1}_{n+k-1}$ bộ $k$ số không âm có tổng bằng $n$. Cũng với ý tưởng của bài toán 2, ta cũng thấy được sẽ có $C^{k-1}_{n-1}$ dãy tăng và $C^{k-1}_{n+k-1}$ dãy không giảm mà phần tử cuối cùng bằng $n$. ### Luyện tập 1. [Doraemon và thử thách đầu tiên [Bản khó] ](https://lqdoj.edu.vn/problem/firstchallenge2) 2. [XXX](http://lequydon.ntucoder.net/Problem/Details/4599) 3. [Tổ hợp](https://lqdoj.edu.vn/problem/combi) 4. [Tam giác Pascal](https://lqdoj.edu.vn/problem/ncr)