快速幂(讲解)

对于快速幂有人会问:要快速幂干什么,cmath库里的pow就很好用啊!

但是你有没有想过他的时间复杂度!假设我们要求a^b,按照朴素算法就是把a连乘b次,这样一来时间复杂度是O(b)也即是O(n)级别,况且有些大佬说:用stl比用循环还慢。但是我们在这里所说的快速幂的目的就是做到快速求幂,快速幂能做到O(logn),快了好多好多。

快速幂的原理是用二分及二进制优化的。

假设我们要求a^b,那么我们在这里如果我们要用快速幂来做这道题,我们可以把b拆成二进制,该二进制的第i位的权为2^(i-1),例如:

当b==11时,a^11=a^(2^0+2^1+2^3)

11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 a^(2^0)*a^(2^1)*a^(2^3) ,有没有发现现在就快多了?

(⊙o⊙)…貌似这两项也不是很好求的样子。。。。

没事,我们在下面还会讲到的。

由于是二进制,很自然地想到用位运算这个强大的工具: &  和 >>

  &运算通常用于二进制取位操作,例如一个数 & 1 的结果就是取二进制的最末位。还可以判断奇偶x&1==0为偶,x&1==1为奇。

  >>运算比较单纯,二进制去掉最后一位。

不多说了,先来看看代码吧。

各种模板

    one。快速幂普通版(未取模)

int kpow(int n,int k)
{
     long long int res=1;
    while(k)
    {
        if(k&1) res*=n;
        n*=n;
        k=k>>1;//每次都将k/2,为使用的二进制,使改代码更快。
    }
    return res;
}

    two。快速幂取余版

int kpow(long long  n,long long  k,long long  mod)
{
     long long int res=1;
    while(k)
    {
        if(k&1) res=(res*n)%mod;
        n=(n*n)%mod;
        k=k>>1;//每次都将k/2,为使用的二进制,使改代码更快。
    }
    return res;
}

three。由于若题目数据太大,会使快速幂时由于是先乘后取余,乘后会导致越界,故可采用模拟乘法,在模拟乘法过程中取余数

即模拟乘法+快速幂

int qpow(long long n,long long k,long long mod)
{
    long long int res=1;
    while(k)
    {
        if(k&1) res=(res*n)%mod;
        n=(n*n)%mod;
        k=k>>1;
    }
    return res;
}
/******************华丽的分割线*****************************/
              /****模拟乘法****/
int Analog multiplication(long long n,long long k,long long mod)
{
    long long  res=0;
    while(k)
    {
        if(k&1)res=(res+n)%mod;
        n=(2*n)%mod;
        k=k>>1;
    }
    return res;
}
            /****快速幂****/
int qpow(long long n,long long k,long long mod)
{
    long long res=1;
    while(k)
    {
        if(k&1) res=Analog multiplication(n,k,mod);
        n=Analog multiplication(n,n,mod);
        k=k>>1;
    }
    return res;
}

代码很短,死记也可行,但最好还是理解一下吧,其实也很好理解,以b==11为例,b=>1011,二进制从右向左算,但乘出来的顺序是 a^(2^0)*a^(2^1)*a^(2^3),是从左向右的。我们不断的让n*=n目的即是累乘,以便随时对ans做出贡献。

  其中要理解n*=n这一步,看:::n*n==n^2,下一步再乘,就是n^2*n^2==n^4,然后同理  n^4*n4=n^8,,,,,see?是不是做到了n-->n^2-->n^4-->n^8-->n^16-->n^32.......指数正是 2^i 啊,再看上  面的例子,a¹¹= a^(2^0)*a^(2^1)*a^(2^3),这三项是不是完美解决了,,嗯,快速幂就是这样。

  顺便啰嗦一句,由于指数函数是爆炸增长的函数,所以很有可能会爆掉int的范围,根据题意决定是用 long long啊还是unsigned int啊还是mod某个数啊自己看着办。

时间: 2024-10-05 08:12:41

快速幂(讲解)的相关文章

【转载】快速幂讲解

转载自:cxcxcxc 快速幂讲解 快速幂这个东西比较好理解,但实现起来到不老好办,记了几次老是忘,今天把它系统的总结一下防止忘记. 首先,快速幂的目的就是做到快速求幂,假设我们要求a^b,按照朴素算法就是把a连乘b次,这样一来时间复杂度是O(b)也即是O(n)级别,快速幂能做到O(logn),快了好多好多.它的原理如下: 假设我们要求a^b,那么其实b是可以拆成二进制的,该二进制数第i位的权为2^(i-1),例如当b==11时   a^11=a^(2^0+2^1+2^3) 11的二进制是101

快速幂讲解

快速幂这个东西比较好理解,但实现起来到不老好办,记了几次老是忘,今天把它系统的总结一下防止忘记. 首先,快速幂的目的就是做到快速求幂,假设我们要求a^b,按照朴素算法就是把a连乘b次,这样一来时间复杂度是O(b)也即是O(n)级别,快速幂能做到O(logn),快了好多好多.它的原理如下: 假设我们要求a^b,那么其实b是可以拆成二进制的,该二进制数第i位的权为,例如当b==11时 11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 ,

POJ 1995 (快速幂)

这道题普通做法会发生溢出且会超时,应当用快速幂来求解. 快速幂讲解 1 #include <cstdio> 2 #include <cmath> 3 using namespace std; 4 int main(){ 5 int Z; 6 scanf("%d",&Z); 7 while(Z--){ 8 int M, H; 9 unsigned long long sum = 0; 10 scanf("%d%d",&M,&am

矩阵快速幂 模板与简单讲解

模板 快速幂模板 1 void solve(matrix t,long long o) 2 { 3 matrix e; 4 5 memset(e.a,0,sizeof(e.a)); 6 7 for (int i = 0;i < d;i++) 8 e.a[i][i] = 1; 9 10 while (o) 11 { 12 if (o & 1) 13 { 14 e = mul(e,t); 15 } 16 17 o >>= 1; 18 19 t = mul(t,t); 20 } 21

快速幂模板及讲解

(这篇其实是我用来练习公式编辑器滴,所以讲的内容略水,大佬们也赏脸看看吧) 定义 快速幂即快速求幂(下文为求a的x次幂模m的结果),但我们一般只在要求对一个数的幂取模时才使用,因为有可能结果很大,有可能long long都存不下,但是因为我们有: \((ab)\%m=(a\%m)(b\%m)\) 通过转换,可得: \((a^x)\%m\) \(= (a\times a\times a\times -\times a(共x个a相乘))\%m\) \(= (a\%m)\times (a\times

小白详细讲解快速幂--杭电oj2035-A^B

Problem Description 求A^B的最后三位数表示的整数.说明:A^B的含义是“A的B次方” Input 输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理. Output 对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行. 简单的说这题就是要求高次幂,有两种方法可以实现. 第一总比较土鳖,每次乘完对1000取余也可以过. 我要讲的是第二种听起来很高大上的方法——快

葫芦娃关于快速幂流程的详细讲解

快速幂的流程大概是这样的,维护一个等式a^b=x^y*z. 比如说现在求3的10次方 第一步:3^10=3^10*1 第二步:3^10*1=9^5*1 第三步:9^5*1=9^4*9 第四步:9^4*9=81^2*9 第五步:81^2*9=6561^1*9 第六步:6561^1*9=1^1*59049 所以3^10=59049 上面总共进行了五次乘法运算,相比较朴素的十次来说,要好一些 经过上面的演算,抽象成自然语言大概是这样: 初始化,x=a,y=b,z=1, 每一次,首先如果y不大于0则退出

快速幂取余算法

下面是一个快速幂的介绍: 先贴一个秦九韶算法(Horner算法)的原理: 设有项的次函数 将前项提取公因子,得 再将括号内的前项提取公因子,得 如此反复提取公因子,最后将函数化为 令 ...... 则即为所求 下面是讲解快速幂的:(By  夜せ︱深   感谢作者) 快速幂取模算法 在网站上一直没有找到有关于快速幂算法的一个详细的描述和解释,这里,我给出快速幂算法的完整解释,用的是C语言,不同语言的读者只好换个位啦,毕竟读C的人较多~ 所谓的快速幂,实际上是快速幂取模的缩写,简单的说,就是快速的求

poj 3070 Fibonacci 矩阵快速幂

题目链接:http://poj.org/problem?id=3070 In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequence are: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, … An alternative formula for t