#include<iostream>
using namespace std;
typedef long long ll;
ll qui(ll a,ll b,ll p)
{
ll res=1;
a%=p;//提前对a取余防止a过大
while(b)
{
if(b&1)//b%2==1
{
res=res*a%p;
}
a=a*a%p;
b>>=1;//右移一位,相当于b/=2
}
return res%p;
}
int main()
{
ll t,a,b,p;
cin>>t;
while(t--)
{
cin>>a>>b>>p;
cout<<qui(a,b,p)<<'\n';
}
return 0;
}
这段代码实现了一个快速幂算法(也称为模幂运算),用于高效地计算 a^bmodp 的值,其中 a、b 和 p 是非负整数,且 p 通常是一个大质数(在密码学和数论中很常见)。快速幂算法通过将指数 b 表示为二进制形式并迭代计算,显著减少了乘法操作的次数,从而提高了效率。
函数 qui(ll a, ll b, ll p)
- 参数:接受三个参数
a
(底数)、b
(指数)、p
(模数)。 - 返回值:返回 abmodp 的结果。
- 实现步骤:
- 初始化结果:
res = 1
,因为任何数的0次方都是1(模意义下也成立)。 - 对底数取模:
a %= p
,防止在后续计算中a
变得过大。 - 迭代处理指数:通过循环,将指数
b
的每一位(二进制)逐一处理。- 如果
b
的当前位是1(即b & 1
),则将res
乘以a
并取模p
。 - 然后,无论
b
的当前位是0还是1,都将a
自乘(a = a * a % p
)并准备处理b
的下一位。注意,这里a
的自乘是在取模p
之后进行的,保证了a
不会过大。 - 通过
b >>= 1
(右移一位,相当于b /= 2
,但更高效),处理b
的下一位。
- 如果
- 返回结果:由于
res
在计算过程中已经对p
取了模,所以最终的res
就是 a^bmodp 的结果。
- 初始化结果:
main
函数
- 输入:首先读取一个整数
t
,表示测试用例的数量。然后,对于每个测试用例,读取三个整数a
、b
和p
。 - 处理:对于每个测试用例,调用
qui
函数计算 abmodp 的值,并输出结果。 - 输出:每个测试用例的结果占一行。
快速幂知识总结
快速幂算法是一种高效的算法,用于计算形如 abmodp 的表达式。它通过以下方式减少乘法操作的次数:
- 二进制表示:将指数
b
表示为二进制形式,例如 b=(bk…b2b1b0)2,其中 bi 是0或1。 - 迭代计算:从 b 的最低位开始,逐位处理。如果当前位是1,则将当前结果乘以底数的某个幂次(该幂次是2的当前位索引次幂,但已经在迭代过程中计算好了),并取模。无论当前位是0还是1,都更新底数的幂次(将其平方并取模),然后处理下一位。
- 优化:在迭代过程中,通过取模操作防止中间结果过大,从而避免了整数溢出的问题。
快速幂算法的时间复杂度为 O(logb),远优于朴素的 O(b) 方法,特别是当 b
非常大时,效率提升尤为显著