洛谷題單指南-分治與倍增-P1226 【模板】快速冪

五月江城發表於2024-09-12

原題連結:https://www.luogu.com.cn/problem/P1226

題意解讀:快速冪模版題。

解題思路:

1、分治法

要計算a^b,可以對b分情況討論:

如果b是偶數,即b = 2t,a^b = a^t * a^t

如果b是奇數,即b = 2t + 1,a^b = a * a^t * a^t

很容易用遞迴實現

100分程式碼:

#include <bits/stdc++.h>
using namespace std;

int a, b, p;

//計算x^y%p
int ksm(int x, int y)
{
    if(y == 0) return 1 % p;
    int t = ksm(x, y / 2);
    if(y % 2 == 0) return 1ll * t * t % p;
    else return 1ll * x * t % p * 1ll * t % p;
}

int main()
{
    cin >> a >> b >> p;
    printf("%d^%d mod %d=%d", a, b, p, ksm(a, b));
}

2、倍增法

基於任意整數都可以轉換成若干個2的次冪之和,如14 = 2^1 + 2^2 + 2^4

這樣一來,計算a^b,如果b=14,可以變成計算a^(2^1 + 2^2 + 2^4)

由於15用二進位制表示為1110,因此可以透過移位操作來列舉14的每一個2的次冪,累乘即可

每移位一次,指數的二進位制位置所表示的值都是之前的2倍,要累乘的值a = a * a,如果當前位是1,說明需要累乘,如果當前位為0,說明不需要累乘

下面模擬一下過程:

設結果res = 1,計算a^14

第一次:判斷1110 & 1 == 0,不需要累乘, 1110右移一位變成111,a = a * a,這時a是初始a^2,res = 1

第二次:判斷111 & 1 == 1, 需要累乘,res = res * a, 111右移一位變成11,a = a * a,這時a是初始a^4,res = 初始a^2

第三次:判斷11 & 1 == 1,需要累乘,res = res * a,11右移一位變成1,a = a * a,這時a是初始a^8,res = 初始a^2*初始a^4

第四次:判斷1 & 1 == 1,需要累乘,res = res * a,1右移一位變成0,結束,res = 初始a^2 * 初始a^4 * 初始a^8 = 初始a^14

100分程式碼:

#include <bits/stdc++.h>
using namespace std;

int a, b, p;

//計算x^y%p
int ksm(int x, int y)
{
    int res = 1;
    while(y)
    {
        if(y & 1) res = 1ll * res * x % p;
        y = y >> 1;
        x = 1ll * x * x % p;
    }
    return res;
}

int main()
{
    cin >> a >> b >> p;
    printf("%d^%d mod %d=%d", a, b, p, ksm(a, b));
}

相關文章