数论--快速幂

一提起幂,大家一定会不约而同的想到pow函数。前一段时间的期末,帮外院的同学备考C语言的时候,发现他们有的函数题或者编程题有特殊要求,就比如不能用某某头文件或某某函数。

如果不让用#include 头文件和pow函数。那在写幂运算的时候就可能会...呐,来个循环。

int sxpow(int a,int n)
{
    int ans=1;
    for(int i=1; i<=n; i++)
        ans*=a;
    return ans;
}

学过计算机语言的都明白,是不是慢极了?来来来,快速幂。

概述:

快速幂就是快速的算幂(有点废话),时间复杂度为 O(log₂N), 与上面的 O(N)相比效率有了极大的提高。

模板:

二进制快速幂

先补充一下位运算的小知识:

  1. b & 1 // b 二进制的最低位,判断和 1 是否相同,相同返回 1,否则返回 0,用于判断奇偶,相当于n%2==1
  2. b>>=1 //把 b 的二进制右移一位,即去掉其二进制位的最低位

来个模板(以a¹¹为例)

int fastpow(int a,int n)
{
    int base=a;//也可以不定义base,直接用a来计算,这里是为了方便解释
    int res=1;//用res返回结果
    while(n)
    {
        if(n&1)//如果n的最后一位是1,表示这个地方需要乘
            res*=base;
        base*=base;//推算乘积,a2->a4->a8....
        n>>=1;//n右移一位,把刚处理过的n的最后一位去掉
    }
    return res;
}

对于上面的程序,执行步骤为:

数论--快速幂_第1张图片

一般式快速幂  (这个就和上边的位运算求幂的模板一样,就是把个别的运算式换了一种表达方法)

int fastpow(int a,int n)
{
    int base=a;
    int res=1;
    while(n)
    {
        if(n%2)
            res*=base;
        base*=base;
        n/=2;
    }
    return r;
}

递归式快速幂

int fastpow(int a,int n)
{
    if(n==1)
        return a;//分治
    int temp=fastpow(a,n/2);
    if(n%2==1)//奇数个a,可以写n&1
        return temp*temp*a;
    else //偶数个a
        return temp*temp;
}

矩阵快速幂

下为矩阵相乘的定义和公式

数论--快速幂_第2张图片

(该图片出自百度百科)

矩阵乘法的代码,结合着上图来看就比较好理解了。

同样,矩阵乘法也满足乘法的一些基本性质(交换律,结合律,分配律等等)。

struct node
{
    int mat[15][15];//定义矩阵
} x,y;
node mul(node x,node y) //矩阵乘法
{
    node tmp;
    for(int i=0; i

给定一个m X m的矩阵A,求它的n次幂,原理就是把矩阵当成变量来操作。所以,矩阵快速幂和快速幂的模板也是大同小异。

node matpow(node x,node y,int num) //矩阵快速幂
{
    while(num)
    {
        if(num&1)
            y=mul(y,x);
        x=mul(x,x);
        num=num>>1;
    }
    return y;
}

矩阵乘法的复杂度是O(len³),快速幂的复杂度为O(log₂num),所以矩阵快速幂的时间复杂度为O(len³ X log₂num)。

矩阵快速幂的应用主要是用来求解递推式,如何把递推关系转换为矩阵却是很大的一个难点。

下图为一些常见的递推关系转换为矩阵的模型,大家自行食用。

数论--快速幂_第3张图片

(该图片转自https://blog.csdn.net/red_red_red/article/details/90208713)

快速幂取模:

幂运算的结果一般会非常大,通常会超过变量类型的最大值,甚至超过内存所放的最大数,所以这类题目一般会要求取模,缩小结果。

根据模运算的性质,在快速幂中取模操作,对aⁿ取模,和先对a取模再做幂运算的结果是一样的,也就是:

                                                                   aⁿ mod m = (a mod m)ⁿ mod m

以一般式快速幂为例:

if(n%2)
    res=(res*base)%mod;
base=(base*base)%mod;

推荐习题:

HDU 1061--求nⁿ的末尾数字

HDU 5392--快速幂取模

POJ 3070--矩阵快速幂的经典题目,算Fibonacci数列

HDU 6030--把递推关系转换成矩阵(女生专场竞赛题目)

HDU 5895--有难度的矩阵快速幂(2016 ACM/ICPC Asia Regional Shenyang Online )

就先推荐这些,大部分题目都是模板题,大家可以自己去学校官网找一些适合自己的题目来AC一下  ( ̄▽ ̄)~*

 

你可能感兴趣的:(数学)