快速幂算法及其在动态规划中的应用(矩阵幂)

本文详细介绍快速幂算法原理及其在计算大整数幂次、矩阵幂次的应用,并通过具体实例展示如何利用快速幂算法提高计算效率。

一、快速幂算法引入

  假如我们有一个需要求2^100的后三位的问题,我们可以利用%运算的性质:
( a ∗ b ) % p = ( a % p ∗ b % p ) % p (a * b)\%p = (a\%p * b\%p)\%p (ab)%p=(a%pb%p)%p
  这意味着我们如果想对 2 100 2^{100} 2100 直接取后三位,也就是取余1000,可以对它的每个因子取余1000,然后把这些因子乘起来再取余1000,得到的结果和直接对 2 100 2^{100} 2100取余1000是一样的。

  常规思路是循环100次,模拟乘100次2的过程。

  但是这样思路写的代码经过时间测试用时有点长,我们能否优化这个O(N)的算法呢?

#include <iostream>
#include <ctime>
using namespace std;
long long normalPower(long long base, long long power)
{
   
   
    int res = 1;
    for (int i = 1; i <= power ; ++i)
    {
   
   
        res *= base;
        res %= 1000;
    }
    return res;
}

int main()
{
   
   
    clock_t start = clock();
    cout << normalPower(2, 1000000000) << endl;
    clock_t end = clock();
    cout << "The cost of calculate is " << double(end - start) / CLOCKS_PER_SEC << endl;
}

二、快速幂算法

  核心思想就是如果幂次是偶数,那么我们可以让底数变成原来的平方,如果幂次是奇数,那么我们可以分解出一个底数,让它与返回结果相乘,然后幂次就是偶数了,通敌,让底数变为原来的平方,当幂次分到0的时候,就意味着我们不能再分解了,结束循环。

long long QuickPower(long long base, long long power)
{
   
   
    int res = 1;
    while (power > 0)
    {
   
   
        if (power % 2 == 0)
        {
   
   
            /*偶数情况 则底数平方 幂次变为原来的一半*/
            base = base * base % 1000;
            power /= 2;
        }
        else
        {
   
   
            /*指数是奇数情况 则拿出一个底数 使得指数变成偶数 然后就可以按照偶数那样操作*/
            res = res * base % 1000;
            --power;
            base = base * base % 1000;
            power /= 2;
        }
        /*直到幂次被削为0次幂时,循环结束,0次幂的时候就无法再进行削指数的操作了*/
    }
    return res;
}

  优化一下重复部分,发现只有奇数有额外操作,可以简化为:

long long QuickPower(long long base, long long power)
{
   
   
    int res = 1;
    while (power > 0)
    {
   
   
        if (power % 2 == 1)
        {
   
   
            res = res * base % 1000;
            --power;
        }
        base = base * base % 1000;
        power /= 2;
        /*直到幂次被削为0次幂时,循环结束,0次幂的时候就无法再进行削指数的操作了*/
    }
    return res;
}

  再优化一下,可以把power % 2 == 1优化为:power & 1 == 1,然后再优化成power & 1,然后power /= 2优化为power >>= 1

long long QuickPower(long long base, long long power)
{
   
   
    int res = 1;
    while (power > 0)
    {
   
   
        if (power & 1)
        {
   
   
            /*幂次为奇数时 需要把一个底数提取出来 然后让power - 1变为偶数*/
            res = res * base % 1000;
            --power;
        }
        /*偶数情况则直接让底数平方 指数除2*/
        base = base * base % 1000;
        power >>= 1;
        /*直到幂次被削为0次幂时,循环结束,0次幂的时候就无法再进行削指数的操作了*/
    }
    return res;
}

  时间复杂度分析:快速幂算法的时

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值