算法刷题AcWing 90. 64位整数乘法——位运算

Posted Ricky_0528

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法刷题AcWing 90. 64位整数乘法——位运算相关的知识,希望对你有一定的参考价值。

a a a b b b p p p取模的值
输入格式
第一行输入整数 a a a,第二行输入整数 b b b,第三行输入整数 p p p
输出格式
输出一个整数,表示 a × b   m o d   p a \\times b\\ mod\\ p a×b mod p
数据范围
1 ≤ a , b , p ≤ 1 0 18 1 \\leq a,b,p \\leq 10^18 1a,b,p1018
输入样例

3
4
5

输出样例

2

①分析

这题使用到的算法为龟速乘,类似于快速幂,也可以用高精度

a × b   m o d   p 这里相当于  b  个  a  相加  m o d   p ,即用加法来表示乘方 因为数据范围很大,相乘就会爆 l o n g   l o n g ,因而要避免让两个数发生乘法 但如果直接一个一个加,加一次就模上一个 p ,这样时间复杂度为 O ( b ) = 1 0 18 超时,需要降低 1 2 ,故考虑二进制 a   m o d   p 2 a   m o d   p 4 a   m o d   p 8 a   m o d   p … … 2 62 a   m o d   p 发现下一个可以由上一个的二倍得到,类似于二进制 可以将 b 转化为二进制表示,设为 ( 10101 ) 2 , b = 2 0 + 2 2 + 2 4 a × b = a + 4 a + 16 a 因而只需要 a 每次乘以二倍模上 p 迭代,然后看 b 的二进制哪些位上为 1 ,为 1 结果就加上当前 a 的值,为 0 则跳过 复杂度就降为了 O ( l o g b ) a\\times b\\ mod\\ p这里相当于\\ b\\ 个\\ a\\ 相加\\ mod\\ p,即用加法来表示乘方\\\\ 因为数据范围很大,相乘就会爆long\\ long,因而要避免让两个数发生乘法\\\\ 但如果直接一个一个加,加一次就模上一个p,这样时间复杂度为O(b)=10^18超时,需要降低\\frac12,故考虑二进制\\\\ a\\ mod\\ p\\\\ 2a\\ mod\\ p\\\\ 4a\\ mod\\ p\\\\ 8a\\ mod\\ p\\\\ ……\\\\ 2^62a\\ mod\\ p\\\\ 发现下一个可以由上一个的二倍得到,类似于二进制\\\\ 可以将b转化为二进制表示,设为(10101)_2,b=2^0+2^2+2^4\\\\ a\\times b=a+4a+16a\\\\ 因而只需要a每次乘以二倍模上p迭代,然后看b的二进制哪些位上为1,为1结果就加上当前a的值,为0则跳过\\\\ 复杂度就降为了O(logb) a×b mod p这里相当于 b  a 相加 mod p,即用加法来表示乘方因为数据范围很大,相乘就会爆long long,因而要避免让两个数发生乘法但如果直接一个一个加,加一次就模上一个p,这样时间复杂度为O(b)=1018超时,需要降低21,故考虑二进制a mod p2a mod p4a mod p8a mod p……262a mod p发现下一个可以由上一个的二倍得到,类似于二进制可以将b转化为二进制表示,设为(10101)2b=20+22+24a×b=a+4a+16a因而只需要a每次乘以二倍模上p迭代,然后看b的二进制哪些位上为1,为1结果就加上当前a的值,为0则跳过复杂度就降为了O(logb)

②代码

#include <cstdio>

typedef long long LL;

LL mul(LL a, LL b, LL p)

    LL res = 0;
    while (b)
    
        if (b & 1)
            res = (res + a) % p;
        a = 2 * a % p;
        b >>= 1;
    
    
    return res;


int main()

    LL a, b, p;
    scanf("%lld%lld%lld", &a, &b, &p);
    
    printf("%lld\\n", mul(a, b, p));
    
    return 0;

③细节分析

LL mul(LL a, LL b, LL p)

    LL res = 0;
    while (b)
    
        if (b & 1) // 判断当前位是否为1
            res = (res + a) % p;
        a = 2 * a % p; // b右移的同时a每次乘2即可得到a、2a...
        b >>= 1;
    
    
    return res;

以上是关于算法刷题AcWing 90. 64位整数乘法——位运算的主要内容,如果未能解决你的问题,请参考以下文章

64位整数乘法讲解-And-AcWing-90. 64位整数乘法-方法二-《算法竞赛进阶指南》

64位整数乘法讲解-And-AcWing-90. 64位整数乘法

64位整数乘法讲解-And-AcWing-90. 64位整数乘法-方法二

ACwing90 64位整数乘法 大数乘法取模

90. 64位整数乘法

AcWing基础算法课Level-3 第一讲 基础算法