考虑以下简单的方法将两个数字相乘。
// A Simple solution that causes overflow when
// value of (a % mod) * (b % mod) becomes more than
// maximum value of long long int
#define ll long long
ll multiply(ll a, ll b, ll mod)
{
return ((a % mod) * (b % mod)) % mod;
}
当乘法不会导致溢出时,上述函数可以正常工作。但是,如果输入数字的乘积结果大于最大限制。
例如,当mod = 10 11 ,a = 9223372036854754775807(最大长整数)和b = 9223372036854775807(最大长整数)时,上述方法失败。请注意,可能存在较小的值,可能会失败。可以有更多的较小值的示例。实际上,任何与之相乘会导致大于最大值的值的集合。
如何避免溢出?
我们可以递归乘法来克服溢出的困难。要乘以a * b,请先计算a * b / 2,然后将其相加两次。为了计算a * b / 2,请计算a * b / 4,依此类推(类似于log n求幂算法)。
// To compute (a * b) % mod
multiply(a, b, mod)
1) ll res = 0; // Initialize result
2) a = a % mod.
3) While (b > 0)
a) If b is odd, then add 'a' to result.
res = (res + a) % mod
b) Multiply 'a' with 2
a = (a * 2) % mod
c) Divide 'b' by 2
b = b/2
4) Return res
下面是实现。
C++
// C++ program for modular multiplication without
// any overflow
#include
using namespace std;
typedef long long int ll;
// To compute (a * b) % mod
ll mulmod(ll a, ll b, ll mod)
{
ll res = 0; // Initialize result
a = a % mod;
while (b > 0)
{
// If b is odd, add 'a' to result
if (b % 2 == 1)
res = (res + a) % mod;
// Multiply 'a' with 2
a = (a * 2) % mod;
// Divide b by 2
b /= 2;
}
// Return result
return res % mod;
}
// Driver program
int main()
{
ll a = 9223372036854775807, b = 9223372036854775807;
cout << mulmod(a, b, 100000000000);
return 0;
}
Java
// Java program for modular multiplication
// without any overflow
class GFG
{
// To compute (a * b) % mod
static long mulmod(long a, long b,
long mod)
{
long res = 0; // Initialize result
a = a % mod;
while (b > 0)
{
// If b is odd, add 'a' to result
if (b % 2 == 1)
{
res = (res + a) % mod;
}
// Multiply 'a' with 2
a = (a * 2) % mod;
// Divide b by 2
b /= 2;
}
// Return result
return res % mod;
}
// Driver code
public static void main(String[] args)
{
long a = 9223372036854775807L, b = 9223372036854775807L;
System.out.println(mulmod(a, b, 100000000000L));
}
}
// This code is contributed by Rajput-JI
Python3
# Python3 program for modular multiplication
# without any overflow
# To compute (a * b) % mod
def mulmod(a, b, mod):
res = 0; # Initialize result
a = a % mod;
while (b > 0):
# If b is odd, add 'a' to result
if (b % 2 == 1):
res = (res + a) % mod;
# Multiply 'a' with 2
a = (a * 2) % mod;
# Divide b by 2
b //= 2;
# Return result
return res % mod;
# Driver Code
a = 9223372036854775807;
b = 9223372036854775807;
print(mulmod(a, b, 100000000000));
# This code is contributed by mits
C#
// C# program for modular multiplication
// without any overflow
using System;
class GFG
{
// To compute (a * b) % mod
static long mulmod(long a, long b, long mod)
{
long res = 0; // Initialize result
a = a % mod;
while (b > 0)
{
// If b is odd, add 'a' to result
if (b % 2 == 1)
{
res = (res + a) % mod;
}
// Multiply 'a' with 2
a = (a * 2) % mod;
// Divide b by 2
b /= 2;
}
// Return result
return res % mod;
}
// Driver code
public static void Main(String[] args)
{
long a = 9223372036854775807L,
b = 9223372036854775807L;
Console.WriteLine(mulmod(a, b, 100000000000L));
}
}
// This code is contributed by 29AjayKumar
输出:
84232501249
感谢Utkarsh Trivedi提出上述解决方案。