快速幂
给定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}} a2b1∗a2b2∗...∗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 p∗a2b2mod 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=a∗a,a22=a4=a2∗a2,a23=a8=a4∗a4...a2i=a2i−1∗a2i−1,根据这一个性质,我们只需要每次对 k k k进行右移的同时对 a a a进行 a = a ∗ a a=a*a a=a∗a的计算即可,不过要注意 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