快速幂取模

引例

求 a^{b} % c的结果,其中0 <= a,b,c <= 1e^{9}

首先考虑O(n)的算法,即b次的a相乘,最后取余c。显然这种算法有两个缺点:

  1. a^{b}在数很大的时候,计算机无法表示;
  2. 线性时间内求解在n很大的时候非常费时。

由此我们引入O(\log n)的快速幂取模算法,来解决上述问题。


快速幂取模原理

首先,快速幂取模得以实现,基础是 (a * b) % c = ((a % c) * (b % c)) % c,此处不再证明这条式子。

其次,我们先将引例中的b用二进制来表示:b = ​​​​​​​​​​​​​​  b0 \cdot 2^{0} + b1 \cdot 2^{1} + b2 \cdot 2^{2} + ... + bn \cdot 2^{n}​​​​​​​,其中b0,b1,b2是b用二进制表示后的低位到高位。

\huge a^{b} = a^{b_{0} \cdot 2^{0} + b_{1} \cdot 2^{1} + b_{2} \cdot 2^{2} +...+ b_{n} \cdot 2^{n}}

         \huge = a^{b_{0} \cdot 2^{0}} \cdot a^{b_{1} \cdot 2^{1}} \cdot a^{b_{2} \cdot 2^{2}} \cdot\cdot \cdot a^{b_{n} \cdot 2^{n}}

由以上式子,我们已经可以设计出快速幂取模算法:

  • 遍历b的每一个二进制位,显然为1的时候才对结果有贡献
  • 对于b的每一个二进制位,如果为1则与ans相乘,同时a不断平方(从式子中可以看出,a的增长为: \huge a,a^{2}, a^{4},a^{8},...,a^{2n})
  • 根据基础的式子,每一步都需要取余c

由于遍历的是b的二进制位数,因此只需要\log n次就可以遍历完,时间复杂度为O(\log n)


完整代码

下面为快速幂取模的算法。

#define ll long long
ll quickMod(ll a, ll b, ll c)
{
  ll ans = 1;
  a = a % c; // 首先将a约束到c范围之内
  while(b)
  {
    if(b&1) ans = (ans * a) % c;
    b = b >> 1;
    a = (a * a) % c;
  }

  return ans;
}

 

下面为矩阵快速幂的算法。矩阵快速幂只是将普通的乘法变成矩阵的乘法,然后初始值设为单位矩阵E,其他均为普通快速幂的框架。

#define ll long long
#define maxn 3
struct Matrix
{
  ll m[maxn][maxn];
  Matrix()
  {
    for(int i = 1; i < maxn; i++)
      for(int j = 1; j < maxn; j++)
    {
      m[i][j] = 1;
    }
  }
};
Matrix Mpow(Matrix m1, Matrix m2)
{

  Matrix ans;
  memset(ans.m, 0, sizeof(ans.m));

  for(int i = 1; i < maxn; i++)
    for(int j = 1; j < maxn; j++)
      for(int k = 1; k < maxn; k++)
        ans.m[i][j] = (ans.m[i][j] + m1.m[i][k] * m2.m[k][j]);


  return ans;
}
Matrix quickMod(Matrix a, ll b)
{
  Matrix ans;
  memset(ans.m, 0, sizeof(ans.m));
  for(int i = 1; i < maxn; i++) ans.m[i][i] = 1;

  while(b)
  {
    if(b&1) ans = Mpow(ans, a);
    b = b >> 1;
    a = Mpow(a, a);
  }

  return ans;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值