给定三个数字a,b和c,使得a,b和c最多为10 16 。任务是计算(a * b)%c
一个简单的((a%c)*(b%c))%c的解决方案在这里不起作用。这里的问题是a和b可能很大,因此当我们计算(a%c)*(b%c)时,它超出了long long int可以容纳的范围,因此会发生溢出。例如,如果a =(10 12 +7),b =(10 13 +5),c =(10 15 +3)。
现在long long int最多可以容纳4 x 10 18 (大约),并且a * b远大于该值。
代替进行直接乘法,我们可以添加find a + a +………。(b次),并在每次添加a时取c模,这样就不会发生溢出。但是,从约束a,b和c的角度来看,这将是低效的。我们必须以某种方式以优化的方式计算(∑ a)%c。
我们可以使用分治法来计算它。主要思想是:
- 如果b是偶数,则a * b =(2 * a)*(b / 2)
- 如果b为奇数,则a * b = a +(2 * a)*((b-1)/ 2)
下面是该算法的实现:
C++
// C++ program to Compute (a*b)%c
// such that (a%c) * (b%c) can be
// beyond range
#include
using namespace std;
typedef long long int ll;
// returns (a*b)%c
ll mulmod(ll a,ll b,ll c)
{
// base case if b==0, return 0
if (b==0)
return 0;
// Divide the problem into 2 parts
ll s = mulmod(a, b/2, c);
// If b is odd, return
// (a+(2*a)*((b-1)/2))%c
if (b%2==1)
return (a%c+2*(s%c)) % c;
// If b is odd, return
// ((2*a)*(b/2))%c
else
return (2*(s%c)) % c;
}
// Driver code
int main()
{
ll a = 1000000000007, b = 10000000000005;
ll c = 1000000000000003;
printf("%lldn", mulmod(a, b, c));
return 0;
}
Java
// Java program to Compute (a*b)%c
// such that (a%c) * (b%c) can be
// beyond range
// returns (a*b)%c
class GFG {
static long mulmod(long a, long b, long c) {
// base case if b==0, return 0
if (b == 0) {
return 0;
}
// Divide the problem into 2 parts
long s = mulmod(a, b / 2, c);
// If b is odd, return
// (a+(2*a)*((b-1)/2))%c
if (b % 2 == 1) {
return (a % c + 2 * (s % c)) % c;
} // If b is odd, return
// ((2*a)*(b/2))%c
else {
return (2 * (s % c)) % c;
}
}
// Driver code
public static void main(String[] args) {
long a = 1000000000007L, b = 10000000000005L;
long c = 1000000000000003L;
System.out.println((mulmod(a, b, c)));
}
}
// This code is contributed by PrinciRaj1992
Python3
# Python3 program of above approach
# returns (a*b)%c
def mulmod(a, b, c):
# base case if b==0, return 0
if(b == 0):
return 0
# Divide the problem into 2 parts
s = mulmod(a, b // 2, c)
# If b is odd, return
# (a+(2*a)*((b-1)/2))%c
if(b % 2 == 1):
return (a % c + 2 * (s % c)) % c
# If b is odd, return
# ((2*a)*(b/2))%c
else:
return (2 * (s % c)) % c
# Driver code
if __name__=='__main__':
a = 1000000000007
b = 10000000000005
c = 1000000000000003
print(mulmod(a, b, c))
# This code is contributed by
# Sanjit_Prasad
C#
// C# program to Compute (a*b)%c
// such that (a%c) * (b%c) can be
// beyond range
using System;
// returns (a*b)%c
class GFG
{
static long mulmod(long a, long b, long c)
{
// base case if b==0, return 0
if (b == 0)
return 0;
// Divide the problem into 2 parts
long s = mulmod(a, b / 2, c);
// If b is odd, return
// (a+(2*a)*((b-1)/2))%c
if (b % 2 == 1)
return (a % c + 2 * (s % c)) % c;
// If b is odd, return
// ((2*a)*(b/2))%c
else
return (2 * (s % c)) % c;
}
// Driver code
public static void Main()
{
long a = 1000000000007, b = 10000000000005;
long c = 1000000000000003;
Console.WriteLine(mulmod(a, b, c));
}
}
// This code is contributed by mits
PHP
Javascript
输出 :
74970000000035