快速幂算法+取模
快速幂
用途: 顾名思义,快速幂就是很快速的幂运算,
复杂度: O(logn)
实现原理:
规律:
- 如果指数是偶数,直接将底数平方,指数处以2;
- 如果指数是奇数,将底数平方,指数除以2,再乘上底数。
模板代码:
ll qpow(ll a,ll b) //a是底数,b是指数
{
ll ans=1;//ans是结果的系数
while(b)
{
if(b%2==1)
{
ans=ans*a;
}
b/=2;
a=a*a;
}
return ans;
}
位运算优化代码:
ll qpow(ll a,ll b)
{
ll ans=1;
while(b)
{
if(b&1)
{
ans=ans*a;
}
a=a*a;
b>>=1;
}
return ans;
}
快速幂取模公式:
(a×b)%m = ((a%m)×(b%m))%m;
推广:
(a × a × a...)%c
= ( (a%c)×(a%c)×(a%c)×... )%c
= (a%c)b %c;
取模模板代码:
ll qpow(ll a,ll b)
{
ll ans=1;
a%=mod;
while(b)
{
if(b%2==1)
{
ans=(ans*a)%mod;
}
b/=2;
a=(a*a) %mod;
}
return ans;
}
位运算优化代码:
ll qpow(ll a,ll b)
{
ll ans=1;
a%=mod;
while(b)
{
if(b&1)
ans=ans*a%mod;
b>>=1;
a=a*a%mod;
}
return ans;
}
龟速乘
因为本来两个数相乘的时间复杂度是O(1),而用了这种方法后时间复杂度变为了O(logN),故称龟速乘。
作用: 用于两个大数相乘还要求取模的情况。
实现方式:
将其中一个乘数分解成2的幂次相加,
比如数字5的二进制表示为101,我们把它看成是\(2^2 + 2^0\),则5 * a可以看成\(2^2 * a + 2^0 * a\),这就是龟速乘。
代码
#include <iostream>
using namespace std;
typedef long long LL;
LL qadd(LL a, LL b, LL p)
{
LL res = 0;
while (b)
{
//将变量b看成是二进制形式,若当前位为1,则更新取模的结果
if (b & 1) res = (res + a) % p;
b >>= 1;
a = (a + a) % p;
}
return res;
}
int main()
{
LL a, b, p;
cin >> a >> b >> p;
cout << qadd(a, b, p) << endl;
return 0;
}