Thuật toán bình phương và nhân là thuật toán tính nhanh lũy thừa tự nhiên của một số (thực hoặc nguyên), trong trường hợp cơ số là số nguyên có thể được rút gọn theo một môđun nào đó.
Phép nâng lên lũy thừa tự nhiên bậc n của số x (x được gọi là cơ số) được định nghĩa từ hệ thức
Với n lớn số phép nhân là rất lớn.
Ví dụ
Công thức đệ quy
Quá trình tính toán trên chính là quá trình tính nhờ công thức đệ quy
- Với n=0 thì xn = 1
- Với n>0 ta có công thức
Như vậy phép tính xn được quy về một số phép bình phương và phép nhân do vậy mà có tên gọi thuật toán bình phương và nhân.
Giải thuật đệ quy
Giải thuật sau tính đệ quy xn(mod m)
Function Square_Multi (int x, n, m){
Var Int Power
If n=0 then return 1
Else {
n:=LShift(n,1)
Power := Square_Multi (int x, n, m)
Power:=(Power^2) mod m
If n BitAnd 1 =0 then
Return Power
Else
Return (Power*x) mod m
}
}
Đoạn code viết bằng java:
public static int binhphuong (int x,int n,int m)
{
int p;
if (n==0) then return 1;
p=binhphuong(x,n/2,m);
if (n%2==0)
return (p*p)%m;
else
return (p*p*x)%m;
}
Giải thuật không đệ quy
Trong giải thuật đệ quy trên đây ta xét tính chẵn lẻ của n và liên tục chia n cho 2 lấy phần nguyên cho đến khi n=0. Thực chất quá trình này chính là tìm các bít của n. Do đó ta có thể thực hiện phép đổi ra số nhị phân trước sau đó tính lũy thừa theo quy tắc bình phương và nhân.
Giải thuật
Đổi n ra số nhị phân ghi vào mảng b[1..k]
Function Power_Modulo(Int x,n,m){
Var Int Power:=1
For i=1 to k do {
Power:=(Power^2) mod m
If b[i]=1 then
Power:=(Power*x) mod m
Return Power
}
Ví dụ
Trong ví dụ sau ta tính 3727(mod 101).
Đổi n=27 ra số nhị phân ta được 27 = 11011(2).
Bảng sau đây tính toán từng bước theo giá trị của các bít của 27.
Khởi tạo p=1.
| b[i] | p = p2 | p = p(mod 101) | p * x | p = (mod 101) |
| 1 | 12 = 1 | 1 | 1 * 37 = 37 | 37 |
| 1 | 372 = 1369 | 56 | 56 * 37 = 2072 | 52 |
| 0 | 522 = 2704 | 78 | - | 78 |
| 1 | 782 = 6084 | 24 | 24 * 37 = 888 | 80 |
| 1 | 802 = 6400 | 37 | 37 * 37 = 1369 | 56 |
Như vậy ta có
3727(mod 101) = 56