📌  相关文章
📜  计算(a * b)%c,使(a%c)*(b%c)可以超出范围

📅  最后修改于: 2021-04-29 09:16:52             🧑  作者: Mango

给定三个数字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。
我们可以使用分治法来计算它。主要思想是:

  1. 如果b是偶数,则a * b =(2 * a)*(b / 2)
  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