快速幂算法

快速幂

给定n组 a i , k i , p i a_i,k_i,p_i ai,ki,pi,对于每组数据,求出 a i k i a_i^{k_i} aikimod p i p_i pi。我们的快速幂算法是这样子的,首先我考虑将 k k k写成二进制的形式,那么这个表示形式一定是可以的,而且是唯一的。那么这样一来假设 k k k= 2 b 1 + 2 b 2 + . . . + 2 b n 2^{b_1} + 2^{b_2} + ... + 2^{b_n} 2b1+2b2+...+2bn,那么 a k a^k ak就可以写成 a 2 b 1 + 2 b 2 + . . . + 2 b n a^{2^{b_1} + 2^{b_2} + ... + 2^{b_n}} a2b1+2b2+...+2bn= a 2 b 1 ∗ a 2 b 2 ∗ . . . ∗ a 2 b n a^{2^{b_1}} * a^{2^{b_2}} * ... * a^{2^{b_n}} a2b1a2b2...a2bn,那么 a k   m o d   p a^k\ mod\ p ak mod p就可以写成 a 2 b 1 m o d   p ∗ a 2 b 2 m o d   p ∗ . . . ∗ a 2 b n m o d   p a^{2^{b_1}} mod\ p* a^{2^{b_2}}mod\ p * ... * a^{2^{b_n}}mod\ p a2b1mod pa2b2mod p...a2bnmod p,(这是有定理可以证明的)。那么现在的关键是如何确定 b 1 , b 2 , . . . , b n b_1,b_2,...,b_n b1,b2,...,bn,其实很简单,就是直接用 k & 1 k\&1 k&1即可然后,然后 k > > = 1 k>>=1 k>>=1,及 k k k右移一位,那么怎么计算 a 2 b i a^{2^{b_i}} a2bi呢,我们可以这样来看, a 2 0 = a 1 , a 2 1 = a 2 = a ∗ a , a 2 2 = a 4 = a 2 ∗ a 2 , a 2 3 = a 8 = a 4 ∗ a 4 . . . a 2 i = a 2 i − 1 ∗ a 2 i − 1 a^{2^0}=a^1,a^{2^1}=a^2=a*a,a^{2^2}=a^4=a^2*a^2,a^{2^3}=a^8=a^4*a^4...a^{2^i}=a^{2^{i-1}}*a^{2^{i-1}} a20=a1,a21=a2=aa,a22=a4=a2a2,a23=a8=a4a4...a2i=a2i1a2i1,根据这一个性质,我们只需要每次对 k k k进行右移的同时对 a a a进行 a = a ∗ a a=a*a a=aa的计算即可,不过要注意 m o d   p mod\ p mod p处理,同时由于中间过程结果可能过大,所以要把中间过程的结果转换成 l o n g   l o n g long\ long long long形式,接下来看一下代码:

#include<iostream>
#include<algorithm>

using namespace std;

typedef long long LL;

int qmi(int a, int k, int p)
{
    int res = 1;
    
    while(k)
    {
        if(k & 1) res = (LL)res * a % p;
        k >>= 1;
        a = (LL)a * a % p;
    }
    
    return res;
}

int main()
{
    int n;
    cin >> n;
    
    while(n --)
    {
        int a, k, p;
        
        scanf("%d%d%d", &a, &k, &p);
        printf("%d\n", qmi(a, k, p));
    }
    
    return 0;
}

第一次用LaTex写公式,虽然麻烦了些,但写出来真的好看。
Y Y D S \mathbb {YYDS} YYDS
Y Y D S \mathscr {YYDS} YYDS

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值