快速幂是很常见的一种高效算法,他有几个变体,下面记录一下。

特别注意,下面的快速幂和矩阵快速幂中,都要根据题目,处理好0^0的状态,不然都会得到1或者单位矩阵。

首先是标准的快速幂。

int Qpow(int a, int b, int mo)
{
    if(a % mo == 0) return 0; //处理0^0的情况
    int ans = 1;
    a %= mo; //控制a的大小
    while(b)
    {
        if(b & 1) ans = ans * a % mo;
        a = a * a % mo;
        b >>= 1;
    }
    return ans;
}

 

既然快速幂可以解决乘方运算的溢出问题,那么就有快速乘解决乘法运算的溢出问题。其实主要就是把乘法变成加法。

int Qmul(int a, int b, int mo)
{
    int ans = 0; //这里和快速幂不同,要注意
    a %= mo; //控制大小
    b %= mo;
    while(b)
    {
        if(b & 1) ans = (ans + a) % mo;
        a = (a << 1) % mo;
        b >>= 1;
    }
    return ans;
}

 

除此之外,快速幂还可以用于矩阵,即矩阵快速幂。若一个矩阵要用快速幂,显然这是一个方阵。

//进行矩阵乘法
void Matrix(int a[maxn][maxn], int b[maxn][maxn], int mo)
{
    int temp[maxn][maxn];
    MS(temp, 0);
    FOR(i, 1, n) FOR(j, 1, n) FOR(k, 1, n) //n为矩阵实际大小
    {
        temp[i][j] = (temp[i][j] + a[i][k] * b[k][j]) % mo;
    }
    memcpy(a, temp, sizeof(temp));
}
//进行矩阵快速幂
void Qmatrix(int A[maxn][maxn], int b, int mo)
{
    int ans[maxn][maxn];
    MS(ans, 0);
    FOR(i, 1, n) ans[i][i] = 1; //n为矩阵实际大小,ans为单位矩阵
    while(b)
    {
        if(b & 1) Matrix(ans, A, mo); //ans*A且把值赋给ans
        Matrix(A, A, mo);
        b >>= 1;
    }
    memcpy(A, ans, sizeof(A)); //答案赋给A
}