AcWing90. 64位整数乘法

题目

求 a a a 乘 b b b 对 p p p 取模的值。

输入格式

第一行输入整数 a a a,第二行输入整数 b b b,第三行输入整数 p p p。

输出格式

输出一个整数,表示 a*b mod p 的值。

数据范围

1 ≤ a , b , p ≤ 1 0 18 1≤a,b,p≤10^{18} 1≤a,b,p≤1018

输入样例

复制代码
3
4
5

输出样例

复制代码
2

思路

C++ 内置的最高整数类型是 64 位,现在 a ∗ b a * b a∗b mod p p p 中的三个变量 a , b , p a, b, p a,b,p 都在 1 0 18 10^{18} 1018 级别,则不存在一个可供强制转换的 128 位整数类型,需要一些特殊的处理办法。

类似快速幂 的思想,把整数 b b b 用二进制表示,即 b = c k − 1 2 k − 1 + c k − 2 2 k − 2 + . . . + c 0 2 0 b = c_{k-1}2^{k-1} + c_{k-2}2^{k-2} + ... + c_02^0 b=ck−12k−1+ck−22k−2+...+c020,则 a ∗ b = c k − 1 ∗ a ∗ 2 k − 1 + c k − 2 ∗ a ∗ 2 k − 2 + . . . + c 0 ∗ a ∗ 2 0 a * b = c_{k-1} * a * 2^{k-1} + c_{k-2} * a * 2^{k-2} + ... + c_{0} * a * 2^{0} a∗b=ck−1∗a∗2k−1+ck−2∗a∗2k−2+...+c0∗a∗20。

因为 a ∗ 2 i = ( a ∗ 2 i − 1 ) ∗ 2 a * 2^{i} = (a * 2 ^{i-1}) * 2 a∗2i=(a∗2i−1)∗2,若已求出 a ∗ 2 i − 1 a * 2^{i-1} a∗2i−1 mod p p p,则计算 ( a ∗ 2 i − 1 ) ∗ 2 (a * 2 ^{i-1}) *2 (a∗2i−1)∗2 mod p p p 时,运算过程中每一步的结果都不超过 2 ∗ 1 0 18 2 * 10^{18} 2∗1018,仍然在 64 位整数 long long 的表示范围内,所以很容易通过 k k k 次递推求出每个乘积项。当 c i = 1 c_i = 1 ci=1 时,把该乘积项累加到答案中即可。

时间复杂度为 O ( l o g 2 b ) O(log_2b) O(log2b)。

代码

cpp 复制代码
#include <cstdio>

using namespace std;

typedef long long ll;

ll mul(ll a, ll b, ll p) {
    
    ll ans = 0;
    
    while (b) {
        if (b & 1) ans = (ans + a) % p;
        b >>= 1;
        a = a * 2 % p;
    }
    
    return ans;
}

int main() {
    ll a, b, p;
    scanf("%lld%ld%lld", &a, &b, &p);
    printf("%lld\n", mul(a, b, p));
    return 0;
}
相关推荐
玩镜的码农小师兄13 天前
[从零开始面试算法] (04/100) LeetCode 136. 只出现一次的数字:哈希表与位运算的巅峰对决
c++·算法·leetcode·面试·位运算·hot100
杨小码不BUG23 天前
灯海寻踪:开灯问题的C++精妙解法(洛谷P1161)
c++·算法·数学建模·位运算·浮点数·信奥赛·csp-j/s
Q741_14724 天前
C++ 位运算 高频面试考点 力扣 面试题 17.19. 消失的两个数字 题解 每日一题
c++·算法·leetcode·面试·位运算
Q741_14725 天前
C++ 位运算 高频面试考点 力扣137. 只出现一次的数字 II 题解 每日一题
c++·算法·leetcode·面试·位运算
Q741_1471 个月前
C++ 位运算 高频面试考点 力扣 371. 两整数之和 题解 每日一题
c++·算法·leetcode·面试·位运算
Q741_1471 个月前
C++ 位运算 高频面试考点 力扣 268. 丢失的数字 题解 每日一题
c++·算法·leetcode·面试·位运算
珍珠是蚌的眼泪2 个月前
LeetCode_位运算
leetcode·位运算·异或·韩明距离·数字的补数
源代码•宸2 个月前
Leetcode—2749. 得到整数零需要执行的最少操作数【中等】(__builtin_popcountl)
c++·经验分享·算法·leetcode·位运算
CUC-MenG2 个月前
2025杭电多校第十场 Cut Check Bit、Multiple and Factor 个人题解
数学·dp·位运算·数位dp·根号分治
Q741_1473 个月前
如何判断一个数是 2 的幂 / 3 的幂 / 4 的幂 / n 的幂 位运算 总结和思考 每日一题 C++的题解与思路
开发语言·c++·算法·leetcode·位运算·总结思考