//a:底数 n:指数 m:模
//取模运算法则:(a * b) % p = (a % p * b % p) % p
借助上面法则,只需要在循环乘积的每一步都进行“取模”运算,而不是等到最后直接对结果“取模”,也能达到同样的效果。
法则是理解重点!
接着传统的求幂算法之所以时间复杂度非常高,就是因为当指数n非常大的时候,需要执行的循环操作次数也非常大。所以快速幂算法的核心思想就是每一步都把指数分成两半,而相应的底数做平方运算。这样不仅能把非常大的指数给不断变小,所需要执行的循环次数也变小,而最后表示的结果却一直不会变。
long long FastPower(long long a, long long n,long long m)
{
long long sum = 1;
while (n > 0)
{ //如果指数为偶数
if (n % 2 == 0)
{
n = n / 2;//把指数缩小为一半
a = a * a % m;//底数平方
}
//如果指数为奇数
else
{
n = n - 1;//把指数减去1,使其变成偶数
sum = sum * a % m;//此时要把指数为奇数时分离出来的底数的一次方
n = n / 2;//此时指数为偶数,可以继续
a = a * a % m;
}
}
return sum;
}
指数缩小一半,底数平方是算法重点!
可以优化!
long long FastPower(long long a, long long n,long long m)
{
long long sum = 1;
while (n > 0)
{
if (n % 2 == 1) //指数为奇数时
{
sum = sum * a % m;//分离出底数的一次方运算,使得分离出得另一半指数是偶数
//则可直接进行下面运算
}
n = n / 2;
a = (a * a) % m;
}
return sum;
}
最后得优化:位运算代替(因为直接在硬件上运行 速度会更快)
#include<stdio.h>
//a:底数 n:指数 m:模
//取模运算法则:(a * b) % p = (a % p * b % p) % p
long long quick_mup(long long a,long long n,long long m)
{
long long res=1%m,t=a;
while(n)
{
if(n&1) //此处等价于if(n%2==1) if(n&0)等价于n%2==0
res = res * t % m;
t= t * t % m;
n >>= 1;//等价于n=n/2
}
return res;
}
int main()
{
long long a,n,m;
scanf("%lld%lld%lld",&a,&n,&m);
printf("%lld",quick_mup(a,n,m));
return 0;
}