快速幂取模算法
因為進位對個位不影響,積的取余等于取余的積取余
#include<stdio.h>int PowerMod(int a, int b, int c) {int ans = 1;int k = a % c;while(b>0)//(k*k % c)2^b %c{if(b % 2 == 1)//如果是奇數(shù)ans = (ans * k) % c;b = b/2;k = (k * k) % c;//k是不斷代入,以代表每一次降一次冪} return ans;}int main() {int T;scanf("%d",&T);while(T--){int n;scanf("%d",&n);int ans=PowerMod(n,n,10);printf("%d\n",ans);}return 0; }1.如果b是偶數(shù),我們可以記k = a2?mod c,那么求(k)b/2?mod c就可以了。
2.如果b是奇數(shù),我們也可以記k = a2?mod c,那么求
((k)b/2?mod c?×?a ) mod c =((k)b/2?mod c * a) mod c?就可以了。
?
那么我們可以得到以下算法:
算法4:
int?ans = 1;
a = a % c;
if(b%2==1)
ans = (ans * a) mod c;?//如果是奇數(shù),要多求一步,可以提前算到ans中
k = (a*a) % c;?//我們?nèi)?/span>a2而不是a
for(int?i = 1;i<=b/2;i++)
{
ans = (ans * k) % c;
}
ans = ans % c;
?
我們可以看到,我們把時間復雜度變成了O(b/2).當然,這樣子治標不治本。但我們可以看到,當我們令k = (a * a) mod c時,狀態(tài)已經(jīng)發(fā)生了變化,我們所要求的最終結(jié)果即為(k)b/2?mod c而不是原來的ab?mod c,所以我們發(fā)現(xiàn)這個過程是可以迭代下去的。當然,對于奇數(shù)的情形會多出一項a mod c,所以為了完成迭代,當b是奇數(shù)時,我們通過
ans = (ans * a) % c;來彌補多出來的這一項,此時剩余的部分就可以進行迭代了。
?
形如上式的迭代下去后,當b=0時,所有的因子都已經(jīng)相乘,算法結(jié)束。于是便可以在O(log b)的時間內(nèi)完成了。于是,有了最終的算法:快速冪算法。
算法5:快速冪算法
?
int?ans = 1;
a = a % c;
while(b>0)
{
?
if(b % 2 == 1)
ans = (ans * a) % c;
b = b/2;
a = (a * a) % c;
}
將上述的代碼結(jié)構(gòu)化,也就是寫成函數(shù):
int?PowerMod(int?a,?int?b,?int?c)
{
int?ans = 1;
a = a % c;
while(b>0)
{
?
if(b % 2 = = 1)
ans = (ans * a) % c;
b = b/2;
a = (a * a) % c;
}
return?ans;
}
本算法的時間復雜度為O(logb),能在幾乎所有的程序設(shè)計(競賽)過程中通過,是目前最常用的算法之一。
總結(jié)
- 上一篇: 【版本发布】JEECG 3.6.2 移动
- 下一篇: JeeWx 微信开发公开课(Jeewx-