【洛谷】P1226 【模板】快速幂||取余运算

关键一:

关键二:

加油!

核心:***将指数(b),转化(看成)二进制进行处理

#include<bits/stdc++.h>
using namespace std;
long long b, a, p, k, ans = 1, c;
int main()
{
    scanf("%lld%lld%lld", &b, &p, &k);
    a = b; c = p;
    while (p > 0)//快速幂
    {
        if (p % 2 != 0)
            ans = ans * b % k;//如果p为单数,乘到ans里面去,然后取模
        b = b * b % k;//每次运算都取模
        p = p >> 1;    //用位运算除2,可能会快一点
    }
    ans %= k;//多年前的代码了……今天突然发现有大佬告知代码错误,仔细一看是在p = 0时没有取模,加上这句话就可以了
    printf("%lld^%lld mod %lld=%lld", a, c, k, ans);//输出
    return 0;
}

1)如果将 aa 自乘一次,就会变成 a^2a2 。再把 a^2a2 自乘一次就会变成 a^4a4 。然后是 a^8a8…… 自乘 nn 次的结果是 a^{2^{n}}a2n 。对吧……

(2)a^xa^y = a^{x+y}axay=ax+y,这个容易。

(3)将 bb 转化为二进制观看一下:

比如 b = (11)_{10}b=(11)10 就是 (1011)_{2}(1011)2 。从左到右,这些 11 分别代表十进制的 8,2,18,2,1。可以说 a^{11} = a^8 × a^2 × a^1a11=aaa1。

为什么要这样表示?因为在快速幂的过程中,我们会把 aa 自乘为 a^2a2,然后 a^2a2 自乘为 a^4a4……像上面第一条说的。



过程会是这样:

(好长,可以不看,如果要阅读下面的模拟过程的话,要慢慢地看噢)

·假设我们拿到了 aa,并且 b = 11b=11。想求 a^{11}a11,但是又不想乘11次,有点慢。

·以电脑视角稍稍观察一下 b = 11b=11,二进制下是 b = 1011b=1011。

·制作一个 basebase。现在 base = abase=a,表示的是,a^1 = aa1=a。待会 basebase 会变的。

·制作一个 ansans,初值 11,准备用来做答案。


while(b > 0)
{

·循环一。看,bb(二进制)的最后一位是 11 吗? 是的。这代表 a^{11} = a^8 × a^2 × a^1a11=aaa1 中的“ × a^1×a1 ”存在。所以 ans *= baseans∗=base

if(b & 1)
	ans *= base;

/*关于 b & 1:
“&”美名曰“按位与”。
x & y 是二进制 x 和 y 的每一位分别进行“与运算”的结果。
与运算,即两者都为 1 时才会返回 1,否则返回 0。
那么 b & 1

          二进制
b     =    1011
1     =    0001
b&1   =    0001

因为 1(二进制)的前面几位全部都是 0,
所以只有 b 二进制最后一位是 1 时,b & 1 才会返回 1。
挺巧妙的,并且很快。)*/

·然后 basebase 努力上升,他通过自乘一次,使自己变成 a^2a2。

base *= base;

同时

b >>= 1;

它把(二进制的)自己每一位都往右移动了。原来的最后第二位,变成了最后第一位!b = (101)_2b=(101)2。

}

·循环二,再看看 bb,最后一位还是 11。这说明有“ × a^2×a2 ”,ans *= baseans∗=base

·basebase 继续努力,通过 base *= basebase∗=base 让自己变成了 a^4a4。然后 bb 也右移 一位。b = 10b=10。


·循环三,可是 bb 的最后一位不再是 11 了,说明不存在“ × a^4×a4 ”。basebase 自我升华,达到了 a^8a8。且 b >>= 1b>>=1。这一步中,答案没有增加,可是毕竟 b > 0b>0,还有希望。


·循环四,bb 的最后一位是 11,这说明“ ×a^8×a8 ”的存在。ans *= baseans∗=base。由于 bb 再右移一位就是 00 了,循环结束。



总的来说,如果 bb 在二进制上的某一位是 11,我们就把答案乘上对应的 a^{2^{n}}a2n。不懂的话,请结合代码理解~

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 快速幂是一种用于快速计算幂运算算法,其基本思想是将指数进行二进制拆分,然后利用指数的二进制表示来快速计算幂运算。在计算过程中,可以利用取余运算来避免数值溢出,提高计算效率。快速幂算法的时间复杂度为O(logn)。 具体实现时,可以使用递归或循环的方式来实现快速幂算法。在递归实现中,需要注意处理指数为负数的情况。在循环实现中,需要注意处理指数为0的情况。 取余运算可以使用%运算符来实现,其含义是求两个数相除的余数。在快速幂算法中,取余运算可以避免数值溢出,提高计算效率。需要注意的是,在取余运算中,除数不能为0。 综上所述,快速幂算法取余运算是计算幂运算时常用的算法运算符,能够提高计算效率,避免数值溢出。 ### 回答2: 快速幂算法是一种优化指数运算算法,通常用于对大整数进行多次乘方运算。该算法的基本思想是将指数拆分成二进制的形式,然后利用指数的二进制表示逐步计算。 具体来说,假设要计算a^b mod c的值,其中a、b、c均为正整数,那么可以先将b转换为二进制的形式,然后从右往左遍历这个二进制数,每次将当前位的值乘到结果中,同时对结果取模,然后将底数a自乘一次,且也要对结果取模。最终得到的结果就是a^b mod c的值。 例如,假设要计算3^13 mod 7的值,将13转换为二进制的形式得到1101,从右往左遍历这个二进制数,开始时结果为1,底数为3,当前位是1,那么将3乘到结果中,并对结果取模得到3,底数自乘得到9 mod 7 = 2;下一位是0,直接将底数自乘,即2*2 mod 7 = 4;再下一位是1,将底数自乘得到16 mod 7 = 2,同时将2乘入结果,结果为3×2 mod 7 = 6;最后一位是1,将底数自乘得到4 mod 7 = 4,同时将4乘入结果,结果为6×4 mod 7 = 3,因此3^13 mod 7的值为3。 快速幂算法的优点是可以快速地计算指数运算,具有较好的时间复杂度。同时,取模运算的存在可以避免产生过多的中间结果,节省了空间复杂度。然而,快速幂算法的缺点是需要将指数转换为二进制形式,这可能会增加算法的编程难度。 ### 回答3: 快速幂是一种用于求解幂运算的快速算法。在进行取余运算时,快速幂算法能够通过对结果取模,使得计算结果更为精确。在计算大数据的幂的运算时,常常可以使用快速幂算法来进行加速运算快速幂算法可以使用递归的方式实现,也可以使用循环的方式实现。递归实现的代码比较简单,但是存在栈空间过大的问题;循环实现的代码虽然有一定的难度,但是能够避免栈空间过大的问题。 在进行取余运算时,我们需要注意的是,如果运算的两个数都很大,那么我们在计算结果时需要特别小心。因为如果直接进行计算,可能会导致数据类型溢出,进而产生错误的结果。为了避免这种情况,我们可以在进行计算时,对结果进行取模处理。 在进行取模运算时,我们需要使用取模定理,也就是(a*b)%p=(a%p)*(b%p)%p。通过这种方式,可以使得计算结果更为精确,也可以避免数据类型溢出的情况发生。如果无法使用取模定理,则需要使用高精度的算法进行取余运算。 总而言之,快速幂算法是一种非常有效的幂运算算法,可以快速地计算出大数据的幂运算结果。在进行取余运算时,需要特别注意数据类型溢出的问题,在进行计算时需要特别小心。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值