快速幂与矩阵快速幂的总结以及应用

1.首先我们来看一个题:

求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”

Input

输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。

Output

对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。

这是一个求幂运算的ACM试题,是一个很简单的东西。但是,前提是你要知道怎么处理。我们来看一下

2.这个题让你把数字求出来再取模显然是不可能的,因为没有这么大的数据类型(当然,我说的数c++)。所以我们可以使用快速幂的方法。快速幂的定义以及使用我就不说了,其实原理十分的简单,比如说让你求2^32,你会把它转换为4^16,继续转化16^8,继续下去是32^4.这样下去,本来需要计算32次,现在只需要4次,这就是快速幂的思想。是不是很简单。基于这个思路,我们来解决一下这个问题。

int PowerMod(long long a, long long b, int n)
{
    int ans = 1;
    a = a % n;
    while (b>0)
    {
        if (b % 2 == 1)
            ans = (ans*a) % n;
        b /= 2;
        a = (a*a) % n;
        b = b >> 1;
    };
    return ans;
}

分析:计算a^b对n的模。首先对n取模,如果是b是奇数,那么当前值更新,如果是偶数,权重更新。就是这么easy.

下面看一下他的推广:很著名的斐波那契数列。其实满足一个矩阵是一个顺序的二阶矩阵。

#include <iostream>
using namespace std;

const int num = 2;
const int mod = 10000;

struct mat {
    int m[num][num];
};

mat I{
    1,0,
    0,1
};

mat mul(mat a, mat b) {
    mat ans;
    for(int i=0;i<num;i++)
        for (int j = 0; j < num; j++) {
            ans.m[i][j] = 0;
            for (int k = 0; k < num; k++)
                ans.m[i][j] += (a.m[i][k] * b.m[k][j]);
            ans.m[i][j] %= mod;
        }
    return ans;
}

mat quick_pow(mat a, long long b) {
    mat ans = I;
    mat tmp = a;
    while (b > 0) {
        if (b & 1)
            ans = mul(ans, tmp);
        tmp = mul(tmp, tmp);
        b >>= 1;
    }
    return ans;
}

int main() {
    long long n;
    mat a{
        1,1,
        1,0
    };
    while (cin >> n&&n!=-1) {
        mat tmp;
        tmp = quick_pow(a, n);
        cout << tmp.m[0][1] << endl;
    }
    return 0;
}

可以如上实现,tem是一个二阶矩阵,其中tem[0][0]是斐波那契数列的第N+1项,紧接着是第N项,然后第二行第一列是第n项,第二列是第n-1项。

以上就是矩阵快速幂的应用

猜你喜欢

转载自blog.csdn.net/weixin_41863129/article/details/81302664