如果我们想暴力求解的话,我们的时间复杂度是O(N)b最大是10的9次方,这时候我们一定会超时
#include <iostream>
using namespace std;
typedef long long LL;
LL a,b,p;LL ret = 1;
int main()
{
cin >> a >> b >> p;
for(int i = 1;i<=b;i++)
{
ret = (ret*a)%p;
}
printf("%lld^%lld mod %lld=%lld",a,b,p,ret);
return 0;
}
这时候我们就要用快速幂的思想来优化我们的算法了
那如果我们求的幂不在这些倍增的序列里面,该怎么办才好呢?
这时候我们就要结合一下二进制了
比如a的11次方 也就是a的(1011)2 次方 实际上就等于a(1*2的三次方+0*2的二次方+1*2的一次方+1*2的零次方) 也就是
好的,时间复杂度解决了,为了防止溢出,我们的取模是随时的
我们讲解一下取模的性质吧
性质1:如果只有加法和乘法:取模可以再任何时候取模(a*b*c*d)%p 等价于 a%p*b%p*c%p*d%p
性质2:如果是减法 为了避免负数,我们可以模加模 也就是((a-b)%p+p)%p
性质3;如果有除法:当计算过程中存在除法的时候,我们取模是会出现错误的,这时候我们需要求个逆元,我们数论章节会讲解的
#include <iostream>
using namespace std;
typedef long long LL;
LL a,b,p;
LL quickcal(LL a,LL b, LL p)
{
LL ret = 1;
while(b)
{
if(b&1) ret=ret*a%p;
a=a*a%p;
b>>=1;
}
return ret;
}
int main()
{
cin >> a >> b >> p;
printf("%lld^%lld mod %lld=%lld\n",a,b,p,quickcal(a,b,p));
return 0;
}