Thuật toán tính $a^b$ bình thường nếu chỉ chạy $b$ lần rồi nhân $a$ vào kết quả sẽ có độ phức tạp $O(b)$, không hiệu quả với $b$ lớn. Đối với thuật toán lũy thừa nhị phân dùng chia để trị chỉ mất độ phức tạp $O(\log b)$, cực kì hiệu quả. ## Thuật toán Xét ví dụ cần tính $5^{20}$. Ta có thể phân tích $5^{20} = \left(5^{10}\right)^2$. Như vậy ta chỉ cần tính $5^{10}$ sau đó bình phương lên là được kết quả. Tương tự với $5^{10} = \left(5^{5}\right)^2$, ta chỉ cần tính $5^5$ rồi bình phương lên để được $5^{10}$. Với $5^5$, ta có thể phân tích thành $5^4 \cdot 5 = \left(5^2\right)^2 \cdot 5$. Và $5^2 = 5^2$. Cuối cùng $5 = 5^0 \cdot 5$, và ta có base case $5^0 = 1$ Vậy ta suy ra được công thức sau: $$a^b = \begin{cases} 1 &\text{nếu } b = 0 \\ \left(a^{b \over 2}\right)^2 &\text{nếu } b > 0 \text{ và } b \text{ chẵn} \\ \left(a^{\left\lfloor b \over 2 \right\rfloor}\right)^2 \cdot a &\text{nếu } b > 0 \text{ và } b \text{ lẻ} \end{cases}$$ ```cpp! long long binpow(long long a, long long b) { if(b == 0) return 1; long long res = binpow(a, b / 2); res *= res; // res ^ 2 if(b % 2 == 1) res *= a; return res; } ``` **Một cách khác không dùng đệ quy:** Xét ví dụ $5^{13}$. Trong hệ nhị phân (bits), $13 = 1101_2 = 1000_2 + 100_2 + 1_2 = 8 + 4 + 1 \Rightarrow 5^{13} = 5^{8+4+1} = 5^8 \cdot 5^4 \cdot 5^1$ ($a^{b+c} = a^b \cdot a^c$). Vì trong hệ nhị phân, mỗi bit $1$ tượng trưng cho một lũy thừa của 2 nên ta sẽ được tích của các lũy thừa với các số mũ là lũy thừa 2. Xét các bit từ phải qua trái, bit thứ 0 (bit đầu tiên) tượng trưng cho $5^{(2^0)}$, bit thứ 1 tượng trưng cho $5^{(2^1)}$, bit thứ 2 tượng trưng cho $5^{(2^2)}$, ..., bit thứ i tượng trưng cho $5^{(2^i)}$. Nếu bit thứ 0 được bật (= 1), ta sẽ nhân $5^{(2^0)}$ vào kết quả, bit thứ 1 được bật thì ta sẽ nhân $5^{(2^1)}$ vào kết quả, bit thứ i được bật thì ta sẽ nhân $5^{(2^i)}$ vào kết quả. ```cpp! long long binpow(long long a, long long b) { long long res = 1; while(b > 0) { if(b & 1) // nếu bit i được bật res *= a; a *= a; // bình phương a hiện tại để tới bit tiếp theo b >>= 1; // dịch 1 bit sang bên phải (tới bit tiếp theo) } return res; } ``` Thông thường, các bài toán sẽ yêu cầu ta tính $a^b \bmod m$ do lũy thừa là một số có thể rất lớn. Ta cũng có thể áp dụng [mod](https://hackmd.io/@khoad/S1R3wgcBa) vào lũy thừa nhị phân.