# PyZ - đệ quy ## Đệ quy là gì? Thứ tự thực hiện hàm: ```python def f(a,b): print('Xin chao f(',a,b,')') print(a * b) print('Tam biet f') def g(x): print('Xin chao g(',x,')') f(x,2*x) print('Tam biet g') g(10) ``` Đoạn code trên in ra: ![](https://i.imgur.com/TAVZNBY.png) Vậy: Hàm gọi sau, lại được thực hiện xong trước! ### Ví dụ cơ bản Đoạn code sau tính $n!$, tích $n$ số đầu tiên ```python= def f(n): print('Dang goi f(' + str(n) + ')') if n <= 1: return 1 return n * f(n-1) print(f(5)) ``` Trong đoạn code trên, nếu không có dòng 3, hàm sẽ chạy vô tận và gặp lỗi như sau: Kết quả in ra: ``` Dang goi f(5) Dang goi f(4) Dang goi f(3) Dang goi f(2) Dang goi f(1) Dang goi f(0) Dang goi f(-1) Dang goi f(-2) Dang goi f(-3) Dang goi f(-4) Dang goi f(-5) Dang goi f(-6) Dang goi f(-7) Dang goi f(-8) ... Dang goi f(-1003) Dang goi f(-1004) Dang goi f(-1005) Dang goi f(-1006) Dang goi f(-1007) Traceback (most recent call last): File "E:\Algo\[J] LQD\dequy.py", line 21, in <module> print(f(5)) File "E:\Algo\[J] LQD\dequy.py", line 19, in f return n * f(n-1) File "E:\Algo\[J] LQD\dequy.py", line 19, in f return n * f(n-1) File "E:\Algo\[J] LQD\dequy.py", line 19, in f return n * f(n-1) [Previous line repeated 1010 more times] File "E:\Algo\[J] LQD\dequy.py", line 17, in f print('Dang goi f(' + str(n) + ')') RecursionError: maximum recursion depth exceeded while pickling an object ``` ## Luôn nhớ: phải có điều kiện dừng. Điều kiện dừng giúp hàm đệ quy không gọi vô tận, và được đặt ở **trên cùng** của hàm này. ## Các bài toán có thể dùng đệ quy ### Tính $a^b (\mod c)$ Dùng tính chất số học: $a^b + a^c = a^{b+c}$ (cùng cơ số, lấy tổng hai số mũ). Nếu $b$ lẻ, ta tính $a^b$ từ $a^{b-1}$ Nếu $b$ chẵn, ta tính từ $a^{b/2}$ ```python= def lt(a,b,c): print('Dang tinh ', a, ' ^ ', b) if b == 0: return 1 if b % 2 == 1: return a * lt(a,b-1,c) % c tam = lt(a, b//2, c) return tam * tam % c ``` Hàm trên chạy rất nhanh, vì sau tầm $2$ phép tính là số mũ $b$ giảm về $0$ Ví dụ với lời gọi hàm `lt(2,127)` ``` Dang tinh 2 ^ 127 Dang tinh 2 ^ 126 Dang tinh 2 ^ 63 Dang tinh 2 ^ 62 Dang tinh 2 ^ 31 Dang tinh 2 ^ 30 Dang tinh 2 ^ 15 Dang tinh 2 ^ 14 Dang tinh 2 ^ 7 Dang tinh 2 ^ 6 Dang tinh 2 ^ 3 Dang tinh 2 ^ 2 Dang tinh 2 ^ 1 Dang tinh 2 ^ 0 ``` ### Tháp Hà Nội Tư tưởng rất hay của đệ quy: Giải bài toán bằng một bài toán tương tự, nhưng nhỏ hơn. Tư duy giống quy nạp của toán: Giả sử tôi chuyển được $n-1$ đĩa thì tôi sẽ chuyển được $n$ đĩa ![](https://i.imgur.com/ACG65sw.png)