#Z1ZMOJ0015. 倍增法快速幂算法

倍增法快速幂算法

当前没有测试数据。

倍增

倍增法(英语:binary lifting),顾名思义就是翻倍。它能够使线性的处理转化为对数级的处理,大大地优化时间复杂度。其基本思想是先通过成倍增长的方式求出状态空间上2的整数次幂项位置的值,再利用这些值组合为需要求解的答案。

指数幂:在数学中,把n个相同的因数a相乘,记做:ana^n,通常求几个相同的因数相乘的运算叫做乘方,乘方的结果叫做幂,在ana^n中,a叫做底数,n叫做指数,ana^n读作 a的n次方 或者 a的n次幂

在C++中,有pow(a,b)函数可以实现a的b次方

幂运算的运算法则:

1、同底数幂运算,底数不变,指数相加

例如:aman=am+na^m*a^n = a^{m+n}

a2a4=a2+4a^2 * a^4 = a^{2+4}

2、幂的乘方运算,底数不变,指数相乘

例如:(am)n=amn(a^m)^n = a^{mn}

数学中的倍增:

1->2->4->8->16->32->64->128代表202122232425262728代表2^02^12^22^32^42^52^62^72^8

如果要计算一个数a,就是a1a^1

倍增一次就是让a*a,即a1a1=a1+1=a2a^{1} * a^1 = a^{1+1} = a^2

再倍增一次就是让a2a^2自乘,即a2a2=a2+2=a4a^{2} * a^2 = a^{2+2} = a^4

再倍增一次,即a4a4=a4+4=a8a^{4} * a^4 = a^{4+4} = a^8

通过这样的倍增规律,如果要求a128a^{128},就只需要倍增6次即可实现

如果求a100a^{100}

这样我们就需要用到快速幂的思想,所谓的快速幂是通过二进制快速计算出来一个数的幂运算

我们可以先写出100的二进制:1100100

然后再把他的转换过程列举出来

a100=a64a32a4=a64+32+4a^{100} = a^{64} * a^{32} * a^{4} = a^{64+32+4}

64+32+4=100,获得幂值

a100a^{100},我们就可以看成:$a^{100} = a^{4} + a^{32} + a^{64} = a^{4}*a^{32}*a^{64}$

由此可得,计算快速幂,实际就是找为1的二进制结果,将结果相乘即可

利用快速幂:计算aba^b的结果

int fast_pow(int a,int b){
  int ans = 1;
  while(b){
    if(b&1){ // 当前二进制位为1
    	ans = ans*a; 
    }
    a = a*a;
    b >> = 1;
  }
  return ans;
}

利用快速幂:计算ab%ma^b \% m的结果

int quick_pow_mod(int a, int b, int m) {
    int ans = 1;
    int base = a % m;
    while (b) {
        if (b&1) { // 当前二进制位为1
            ans = (ans * base) % m;
        }
        base = (base * base) % m;
        b >> = 1;// 右移一位,相当于n除以2
    }
    return ans;
}

完成下面任务:

a的b次方

a的b次方%m