问题
求出abmodc的值,其中a,b,c是整数,且0<a,c<109,0<b<1018
算法设计
暴力算法
考虑用循环直接求出ab的值,最后对c取模。
1 2 3 4 5 6
| long long ans=1; for (long long i=1;i<=b;i++) { ans*=a; } ans%=c;
|
这个代码其实有两个缺陷。
- 时间复杂度为O(b),即要进行1018次运算,一般情况下计算机在1s内无法完成。
- ans会超过long long范围。
下面对其进行优化。我们来看看取模的性质:
(a∗b)modc=((amodc)∗(bmodc))modc
所以我们可以在每一次乘a的时候都对c取模,即
这样我们就解决了缺陷2。但是时间复杂度并没有优化,还有没有别的办法呢?
快速幂算法
我们首先考虑一下手算310,310=(32)5=95=9∗94=9∗812=9∗(812)1,很容易发现规律。而且,这个算法时间复杂度为O(log2b),时间大大减少。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| typedef long long ll; ll fast_pow(ll a,ll b,ll c) { ll ans=1; a%=c; while (b) { if (b%2==1) { ans=(ans*a)%c; } a=(a*a)%c; b/=2; } return ans; }
|
补充:费马小定理
若p为素数,a为正整数,且p,a互质。则有ap−1=1modp。