【牛客】A. a^b%p <位运算>

文章介绍了如何使用位运算来计算a的b次方对p取模的值,主要涉及快速幂算法的原理和步骤。通过将指数b转换为二进制,从右到左判断每一位,每次迭代更新a和结果ans,同时避免数值溢出问题,最终得出a^b模p的结果。
摘要由CSDN通过智能技术生成

牛客网0x01 基本算法-位运算

【牛客】A. a^b%p

求 a 的 b 次方对 p 取模的值,其中 0 <= a,b,p <= 1 0 9 10^9 109, p>0

输入描述:
三个用空格隔开的整数a,b和p。

输出描述:
一个整数,表示 a b a^b ab m o d mod mod p p p 的值。

示例输入

2 3 9

输出

8

题解

简单理解版:
只考虑实现a的b次方:快速幂
计算 a b a ^ b ab,如果把 b b b 写成 2 进制,如 13 的二进制 1101,于是 3 号位 、2号位、0号位就都是1,那么就可以得到 13 = 2 3 2^3 23 + 2 2 2^2 22 + 2 1 2^1 21 = 8 + 4 + 1。所以 a 13 a ^{13} a13 = a 8 a^8 a8 * a 4 a^4 a4 * a 1 a^1 a1

核心一:
b b b 转换成二进制,然和将 b b b 的二进制数从右到左判断,如果判断为1,则 ans 乘上当前的次方。eg: 3 5 3^5 35-> 3 101 3^{101} 3101:第零位表为1,则 ans 就要乘 a 2 0 a^{2^{0}} a20,然后第一位为0,不操作,第二位为1,ans乘上 a 2 2 a^{2^{2}} a22。程序中:ans = 1(ans的初始值) * a 2 0 a^{2^{0}} a20 (第一次操作) * a 2 2 a^{2^{2}} a22(第二次操作)

核心二:
每次循环的时候不管要不要对ans进行操作,都要对 a 进行一次操作,即a = a * a,假如到了第 n 轮循环,此时正在判断 b 的二进制的第 n-1 位是否为1。又因为 a 在第一次进入循环时,为 a 1 a^1 a1 ,即 a 2 0 a^{2^{0}} a20 ,那么第n次循环就是 a 2 n − 1 a^{2^{n-1}} a2n1,正好 b 正在判断第 n-1 位,此时如果为1,则直接将ans = ans * a 即可。

public class Solution {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        long a, b, p, ans = 1;
        a = in.nextLong();
        b = in.nextLong();
        p = in.nextLong();

        //首先可以将a的b次方转化为二进制表示,然后用一个b&1的与运算,判断一下该二进制表示下第i位是否为1,如果为1结果为true,否则为false,
        while (b != 0) {
//            System.out.println("当前a为:" + a);
//            System.out.println("当前b为:" + Long.toString(b, 2));

            //b转二进制数,最后一位是1
            if ((b % 2 ) != 0) {        //或者(b & 1) ==1 //b转为2进制后当前为是1,需要乘上
                ans = ans * a ;
//                System.out.println("当前ans为:" + ans);
            }
            a = a * a ;
            //b右移一位
            b >>= 1;
        }

        System.out.println(ans % p);
    }
}

进阶为了不让大数爆掉,变为快速幂:

import java.util.Scanner;

public class Solution {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        long a, b, p, ans = 1;
        a = in.nextLong();
        b = in.nextLong();
        p = in.nextLong();

        //首先可以将a的b次方转化为二进制表示,然后用一个b&1的与运算,判断一下该二进制表示下第i位是否为1,如果为1结果为true,否则为false,
        while (b != 0) {
            //b转二进制数,最后一位是1
            if ((b % 2 ) != 0) {        //或者(b & 1) ==1 //b转为2进制后当前为是1,需要乘上
                ans = ans * a % p;      //取余p是为了防止程序爆掉
            }
            a = a * a % p;              //取余p是为了防止程序爆掉
            //b右移一位
            b >>= 1;
        }
        System.out.println(ans % p);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Koma_zhe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值