highlight: a11y-dark
【二进制快速幂】
对于幂计算m^n,比如 5 ^7, 我们可以将7改写为二进制111,然后可以对5^7进行分解。
57=5^(1*2 ^ 0)5^(1 * 2 ^ 1 ) 5^(1 * 2 ^2);
不难发现,分解后每项的指数的计算,从宏观上看,我们可以发现我们把原本的6次乘法变成了,2次乘法,当然在计算机里面没有乘法的概念,乘法其实质就是累加,从这个方面来看,其提升的效率比我们想象的还要大。
下面我来讲讲具体实现。
1.首先我们来实现每项指数的递增,也就是2^0-> 2^1-> 2^2(1->2->4),
我们可以设第一项(5^(1* 2 ^0))为x,然后我们可以发现每往后一项,我们只需要对前一项进行平方处理,就相当于实现了递增。比如
5^(1 * 2 ^ 1 )=(5^(1* 2 ^0)) * 5^(1* 2 ^0)
5^(1 * 2 ^ 2 )=5^(1 * 2 ^ 1 ) * 5^(1 * 2 ^ 1 )
5^(1 * 2 ^ 3 )=5^(1 * 2 ^ 2 ) * 5^(1 * 2 ^ 2 )
2.然后就是关于系数的处理,也就是1* 2^0 ,0* 2^1 …的二进制系数的处理。
1)我们可以通过n&1获取末尾的数,如果为奇数则说明需要把当前乘积项乘入最终结果
2)然后通过>>或者/2刷新末尾数。
循环1) 2)直到n为0;
long long Pow(long long x,long long n)
{
long long ans=x,res=1;
while (n)
{
if(n&1)
{
res=res*ans;
}
ans*=ans;
n>>=1;
}
return res;
}
【快速幂取模】
关于大数取模我们根据 总数取模=各因子取模的积 取模
ab=((a%n)(b%n))%n;注意指数不能取模,根据这个公式我们可以在快速幂的基础上进行简单修改就行
#include <iostream>
using namespace std;
long long Pow(long long x,long long n,long long a)
{
long long ans=x,res=1;
while (n)
{
if(n&1)
{
res=(res*ans)%a;
}
ans=(ans*ans)%a;
n>>=1;
}
return res;
}
关于这个问题,可以来做一下这个题目 数组元素的最小非零乘积