快速幂

Posted psephurus-gladius-zdx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速幂相关的知识,希望对你有一定的参考价值。

引入

在求解式子amod k时,我们通常使用循环语句进行求解。但当b的值很大,例如达到了109时,该式子的求解时间消耗就非常大了。因此,我们需要思考另外的方法,使得快速求幂成为可能。

引理

引理1

对于ab(a,b∈Z+),当b为偶数时,它等于ab/2·ab/2,当b为奇数时,它等于a⌊b/2⌋·a⌊b/2⌋·a。

引理2

陈述

对于x=p·q(x,p,q∈Z+),有x mod k=(p mod k)(q mod k)mod k。

证明

设p=a·k+c,q=b·k+d,

则x=(a·k+c)(b·k+d)=a·b·k2+a·d·k+b·c·k+c·d,

∴x mod k=c·d mod k,

又∵(p mod k)(q mod k)mod k=c·d mod k,

∴x mod k=(p mod k)(q mod k)mod k。

方法

根据以上两个引理,我们可以知道,对于amod k,当b为偶数时,它等于(ab/2 mod k)·(ab/2 mod k)mod k,当b为奇数时,它等于(a⌊b/2⌋ mod k)·(a⌊b/2⌋ mod k)·(a mod k)mod k。这个式子可以递归进行下去。这样,我们可以将求幂运算进行优化,使它的时间复杂度降低至O(log n)。

技术图片
 1 long long quick_power(long long a,long long b,long long mod)
 2 {
 3     long long result=1,t=a;
 4     while(b)
 5     {
 6         if(b&1)
 7             result=result*t%mod;
 8         t=t*t%mod;
 9         b>>=1;
10     }
11     return result%mod;
12 }
快速幂函数

例题

·LibreOJ #10196 越狱/洛谷 P3197 [HNOI2008]越狱

·题目描述

监狱有连续编号为1到n的n个房间,每个房间关押一个犯人。有m种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人信仰的宗教相同,就可能发生越狱。求有多少种状态可能发生越狱。(结果对100003取余)

·题目分析

求有多少种状态可能发生越狱,听起来是一个很难的问题。我们不妨换一种角度思考,求出有多少种状态不会发生越狱,再用总状态数减去这个数目,就得到了可能发生越狱的状态数。

由于有m种宗教,n个房间,根据乘法原理,总状态数为mn。而求有多少种状态不会发生越狱,对于第一个人,可以任意信仰哪一种宗教,而对于之后的每一个人,只需要保证与前面的人信仰的宗教不相同即可,状态数为m·(m-1)n-1。我们要求的答案即为(mn-m·(m-1)n-1)mod 100003。

这里有一点需要注意。取余运算中,mn mod 100003的结果可能小于m·(m-1)n-1 mod 100003,减法操作可能出现负数,再次取余将会变成负数而非我们想要的正数。因此,我们应该在进行减法操作之前加上100003,避免负数的出现。

·代码

技术图片
 1 #include<cstdio>
 2 using namespace std;
 3 long long m,n;
 4 const int MOD=100003;
 5 long long quick_power(long long a,long long b,long long k)
 6 {
 7     long long result=1,t=a;
 8     while(b)
 9     {
10         if(b&1)
11             result=result*t%k;
12         t=t*t%k;
13         b>>=1;
14     }
15     return result%k;
16 }
17 int main()
18 {
19     scanf("%lld%lld",&m,&n);
20     printf("%lld",(quick_power(m,n,MOD)+MOD-quick_power(m-1,n-1,MOD)*m%MOD)%MOD);
21     return 0;
22 }
越狱

 

以上是关于快速幂的主要内容,如果未能解决你的问题,请参考以下文章

矩阵快速幂

快速幂

快速幂

快速幂乘法&快速幂取余

快速幂和慢速乘

快速幂解法