给定整数a,b,m。查找(a * b)mod m,其中a,b可能很大,并且它们的直接相乘可能会导致溢出。但是,它们小于允许的long long long int最大值的一半。
例子:
Input: a = 426, b = 964, m = 235
Output: 119
Explanation: (426 * 964) % 235
= 410664 % 235
= 119
Input: a = 10123465234878998,
b = 65746311545646431
m = 10005412336548794
Output: 4652135769797794
天真的方法是使用任意精度的数据类型,例如Python的int或Java的Biginteger类。但是这种方法将不会有成果,因为将字符串内部转换为int然后执行操作将导致二进制数系统中加法和乘法运算的速度变慢。
有效的解决方案:由于a和b可能是非常大的数字,所以如果我们尝试直接相乘,则肯定会溢出。因此,我们使用乘法的基本方法,即
a * b = a + a +…+ a(b次)
因此我们可以轻松计算加法的值(模m下),而无需任何
在计算中溢出。但是,如果我们试图反复加起来的价值b乘以那么它肯定会超时值较大的B的,因为这种方法的时间复杂度将成为O(B)。
因此,我们以一种更简单的方式划分了上述重复步骤,即
If b is even then
a * b = 2 * a * (b / 2),
otherwise
a * b = a + a * (b - 1)
下面是描述以上解释的方法:
C++
// C++ program of finding modulo multiplication
#include
using namespace std;
// Returns (a * b) % mod
long long moduloMultiplication(long long a,
long long b,
long long mod)
{
long long res = 0; // Initialize result
// Update a if it is more than
// or equal to mod
a %= mod;
while (b)
{
// If b is odd, add a with result
if (b & 1)
res = (res + a) % mod;
// Here we assume that doing 2*a
// doesn't cause overflow
a = (2 * a) % mod;
b >>= 1; // b = b / 2
}
return res;
}
// Driver program
int main()
{
long long a = 10123465234878998;
long long b = 65746311545646431;
long long m = 10005412336548794;
cout << moduloMultiplication(a, b, m);
return 0;
}
// This code is contributed
// by Akanksha Rai
C
// C program of finding modulo multiplication
#include
// Returns (a * b) % mod
long long moduloMultiplication(long long a,
long long b,
long long mod)
{
long long res = 0; // Initialize result
// Update a if it is more than
// or equal to mod
a %= mod;
while (b)
{
// If b is odd, add a with result
if (b & 1)
res = (res + a) % mod;
// Here we assume that doing 2*a
// doesn't cause overflow
a = (2 * a) % mod;
b >>= 1; // b = b / 2
}
return res;
}
// Driver program
int main()
{
long long a = 10123465234878998;
long long b = 65746311545646431;
long long m = 10005412336548794;
printf("%lld", moduloMultiplication(a, b, m));
return 0;
}
Java
// Java program of finding modulo multiplication
class GFG
{
// Returns (a * b) % mod
static long moduloMultiplication(long a,
long b, long mod)
{
// Initialize result
long res = 0;
// Update a if it is more than
// or equal to mod
a %= mod;
while (b > 0)
{
// If b is odd, add a with result
if ((b & 1) > 0)
{
res = (res + a) % mod;
}
// Here we assume that doing 2*a
// doesn't cause overflow
a = (2 * a) % mod;
b >>= 1; // b = b / 2
}
return res;
}
// Driver code
public static void main(String[] args)
{
long a = 10123465234878998L;
long b = 65746311545646431L;
long m = 10005412336548794L;
System.out.print(moduloMultiplication(a, b, m));
}
}
// This code is contributed by Rajput-JI
Python 3
# Python 3 program of finding
# modulo multiplication
# Returns (a * b) % mod
def moduloMultiplication(a, b, mod):
res = 0; # Initialize result
# Update a if it is more than
# or equal to mod
a = a % mod;
while (b):
# If b is odd, add a with result
if (b & 1):
res = (res + a) % mod;
# Here we assume that doing 2*a
# doesn't cause overflow
a = (2 * a) % mod;
b >>= 1; # b = b / 2
return res;
# Driver Code
a = 10123465234878998;
b = 65746311545646431;
m = 10005412336548794;
print(moduloMultiplication(a, b, m));
# This code is contributed
# by Shivi_Aggarwal
C#
// C# program of finding modulo multiplication
using System;
class GFG
{
// Returns (a * b) % mod
static long moduloMultiplication(long a,
long b,
long mod)
{
long res = 0; // Initialize result
// Update a if it is more than
// or equal to mod
a %= mod;
while (b > 0)
{
// If b is odd, add a with result
if ((b & 1) > 0)
res = (res + a) % mod;
// Here we assume that doing 2*a
// doesn't cause overflow
a = (2 * a) % mod;
b >>= 1; // b = b / 2
}
return res;
}
// Driver code
static void Main()
{
long a = 10123465234878998;
long b = 65746311545646431;
long m = 10005412336548794;
Console.WriteLine(moduloMultiplication(a, b, m));
}
}
// This code is contributed
// by chandan_jnu
PHP
>= 1; // b = b / 2
}
return $res;
}
// Driver Code
$a = 10123465234878998;
$b = 65746311545646431;
$m = 10005412336548794;
echo moduloMultiplication($a, $b, $m);
// This oce is contributed by ajit
?>
输出:
4652135769797794
时间复杂度: O(log b)
辅助空间: O(1)
注意:只有在标准数据类型中可以表示2 * m时,以上方法才有效,否则会导致溢出。