【牛客】A. a^b%p

牛客网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);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_44033208/article/details/131885033