幂运算取模

2019-04-13 12:22发布

class="markdown_views prism-atom-one-light"> 快速幂也就是我们求解ab mod k" role="presentation">ab mod k这种类型的式子会用

1. 解法一 暴力求解

暴力求解也就是类似下面代码

for(int i = 0;i {
a *=a;
}
a%=k;

这种方法是不可取的
例如:
21003% 3" role="presentation">21003% 3 是非常消耗我们的计算资源的。
- - 缺点1:在我们在之后计算指数的过程中,计算的数字不都拿得增大,非常的占用我们的计算资源(主要是时间,还有空间)
- - 缺点2:我们计算的中间过程数字大的恐怖,我们现有的计算机是没有办法记录这么长的数据的,所以说我们必须要想一个更加高效的方法来解决这个问题

2. 解法二 引入 取模运算

在引入快速幂之前我们先了解一下取模运算 (ab)% k==(a% k)(b% k)% k" role="presentation">(ab)% k==(a% k)(b% k)% k
证明
x=am+b" role="presentation">x=am+b
y=cm+d" role="presentation">y=cm+d
xy=(am+b)(cm+d)=(acm)2+(ad+bc)m+bd=bd(modm)" role="presentation">xy=(am+b)(cm+d)=(acm)2+(ad+bc)m+bd=bd(modm)
x=b mod my=d mod m" role="presentation">x=b mod my=d mod m 得解(ab)% k==(a% k)(b% k)% k" role="presentation">(ab)% k==(a% k)(b% k)% k 然后 我们的式子就可以变成 (2 mod 3)1003 mod 3" role="presentation">(2 mod 3)1003 mod 3 这时我们的代码可以变成 int i = (a%k); //i代表我们每次运算时要乘的数字 for(;b>1;b--){ a%=k; //a取模 a=a*i; } a%=k; 但这样还不够,当我们b足够大时,我们要进行b次实验。这样还是会浪费许多时间

3. 解法三 引入幂运算的取模运算

前面引入了取模运算在这里我们再来讲一下 一种新的幂运算
ab=(a2)b2" role="presentation">ab=(a2)b2
由这个公式可以把我们的运算变成了b2" role="presentation">b2次。
比如21000000072100000089mod 45987" role="presentation">21000000072100000089mod 45987 这样用上面的方式运算时肯定要超时的。 我们就可以用这个
步骤如下:
①先判断b能否被整除
因为我们的的最终结果将在 B2==1" role="presentation">B2==1时出结果
若不能整除 我们的res=ares%k" role="presentation">res=ares%k 一方面使我们的b始终为偶数,一方面也记录了我们的答案
②计算 a2%k" role="presentation">a2%k
代码如下 long res = 1; for(;b>1;b/=2){ if(b/2==1) { res = res*a%k; } a=(a*a)%k; } 例题: