数论 —— 快速幂
【概述】
快速冪就是利用二進(jìn)制的性質(zhì)來(lái)快速計(jì)算底數(shù)的 n 次冪,時(shí)間復(fù)雜度為 O(log?N), 與樸素的 O(N) 相比效率有了極大的提高。
但有時(shí)指數(shù)十分大,利用高精來(lái)寫(xiě)可能會(huì)超時(shí),此時(shí)就需要十進(jìn)制快速冪。
【求位數(shù)公式】
有時(shí)僅要求求 2 的 n 次冪的位數(shù),這里有一個(gè)神奇的求位數(shù)公式:floor(log(2)/log(10)*n+1)
double res=n*log10(2)+1; cout<<int(res)<<endl;【二進(jìn)制快速冪】
以求 a 的 b 次方為例
將 b 轉(zhuǎn)換成二進(jìn)制數(shù),該二進(jìn)制數(shù)第 i 位的權(quán)為:?
例如:
11 的二進(jìn)制是 1011,即:11 = 23×1 + 22×0 + 21×1 + 2o×1
因此,我們將計(jì)算 a11 轉(zhuǎn)化為計(jì)算?
遞歸公式:
可借助位運(yùn)算來(lái)實(shí)現(xiàn):
【二進(jìn)制快速冪取模】
所謂二進(jìn)制快速冪取模,就是計(jì)算給出 a,b,m 三個(gè)數(shù),快速計(jì)算??的值
分析:以求??為例
因此,可遞歸的對(duì) n 進(jìn)行二進(jìn)制分解,在進(jìn)行快速冪運(yùn)算的同時(shí)進(jìn)行求模。
int powMod(int a, int b, int m){int res=1;while(b){if(b&1)res=(res*a)%m;a=(a*a)%m;b>>=1;}return res; }【快速乘法的二進(jìn)制快速冪取模】
當(dāng)數(shù)非常大時(shí),計(jì)算 (a*b)%m 使用 long long 也有可能爆精度,此時(shí)需要利用快速乘法,將轉(zhuǎn)乘法為加法,在模擬的同時(shí)不斷求模
LL multMod(LL a,LL b,LL m){//res=(a*b)%ma%=m;b%=m;LL res=0;while(b){if(b&1)res=(res+a)%m;a=(a<<=1)%m;b>>=1;}return res%m; } LL powMod(LL a, LL b, LL m){//res=(a^b)%mLL res=1;LL k=a;while(b){if((b&1))res=multMod(res,k,m)%m;k=Mult_Mod(k,k,m)%m;b>>=1;}return res%m; }【十進(jìn)制快速冪】
考慮到指數(shù)十分大的情況,例如:,此時(shí)用 python 或 Java 大數(shù)寫(xiě)二進(jìn)制快速冪會(huì)超時(shí),這個(gè)時(shí)候就需要用十進(jìn)制快速冪來(lái)解決。
十進(jìn)制快速冪與二進(jìn)制快速冪沒(méi)有本質(zhì)區(qū)別,只是拆分指數(shù)的方法一個(gè)是以十進(jìn)制,一個(gè)是以二進(jìn)制。
例如:
char b[100007]; LL tenthPow(LL a,LL len,LL mod) {LL res=1;while(len>=0){LL cnt=b[len]-'0';LL cur=a;for(int i=1; i<=cnt; i++)res=res*a%mod;for(int i=1; i<10; i++)cur=cur*a%mod;//進(jìn)位a=cur;res%=mod;len--;}return res; } int main(){LL a,mod;scanf("%lld",&a);scanf("%s",b);//字符串讀入指數(shù)scanf("%lld",&mod);LL len=strlen(b);LL res=tenthPow(a,len-1,mod);printf("%lld^%s %% %lld = %lld",a,b,mod,res);return 0; }【例題】
- 麥森數(shù)(洛谷-P1045)(快速冪+高精度):點(diǎn)擊這里
- 取余運(yùn)算||快速冪(洛谷-P1226)(快速冪取模):點(diǎn)擊這里
- Rightmost Digit(HDU-1061)(快速冪取模):點(diǎn)擊這里
- Leading and Trailing(LightOJ-1282)(快速冪取模+快速冪取高位):點(diǎn)擊這里
- Pupu(HDU-3003)(公式推導(dǎo)+快速冪取模):點(diǎn)擊這里
- 歐拉定理(洛谷-P5091)(十進(jìn)制快速冪):點(diǎn)擊這里
總結(jié)
- 上一篇: 扩号匹配问题(信息学奥赛一本通-T120
- 下一篇: Network of Schools(P