📌  相关文章
📜  模块化除法((x1 * x2…。xn)/ b)mod(m)

📅  最后修改于: 2021-06-26 16:53:22             🧑  作者: Mango

给定整数x1,x2,x3……xn,b和m,我们应该找到((x1 * x2….xn)/ b)mod(m)的结果。
示例1:假设我们需要找到(55C5)%(1000000007),即((55 * 54 * 53 * 52 * 51)/ 120)%1000000007
天真的方法:

  1. 只需计算乘积(55 * 54 * 53 * 52 * 51)=说x,
  2. 将x除以120,然后取其模数为1000000007

使用模乘逆:
仅当x1,x2,x3….xn的值较小时,上述方法才有效。
假设我们需要找到x1,x2,….xn在〜1000000(10 ^ 6)范围内的结果。因此,我们将不得不利用模块化数学规则,即:
(a * b)mod(m)=(a(mod(m))* b(mod(m)))mod(m)
请注意,以上公式对于模乘有效。没有类似的除法公式。
即(a / b)mod(m)!= a(mod(m))/ b(mod(m))

  1. 因此,我们需要找出b说i的模乘逆,然后将’i’与a相乘。
  2. 在此之后,我们将必须取所得结果的模数。
    即((x1 * x2 …. xn)/ b)mod(m)= [(x1 * x2 …. xn)* i)mod(m)=((x1)mod(m)*(x2)mod(m )* ….(xn)mod(m)*(i)mod(m))mod(m)

注意:要找到模乘逆,我们可以使用扩展Eucledian算法或Fermat的Little定理。
示例2:让我们假设必须找到(55555C5)%(1000000007),即((55555 * 55554 * 55553 * 55552 * 55551)/ 120)%1000000007。

C++
// To run this code, we need to copy modular inverse
// from below post.
// https://www.geeksforgeeks.org/multiplicative-inverse-under-modulo-m/
 
int main()
{
    // naive method-calculating the result in a single line
    long int naive_answer = ((long int)(55555 * 55554 *
                55553 * 55552 * 55551) / 120) % 1000000007;
 
 
    long int ans = 1;
 
    // modular_inverse() is a user defined function
    // that calculates inverse of a number
    long int i = modular_inverse(120, 10000007);
 
    // it will use extended Eucledian algorithm or
    // Fermat’s Little Theorem for calculation.
    // MMI of 120 under division by 1000000007
    // will be 808333339
    for (int i = 0; i < 5; i++)
        ans = (ans * (55555 - i)) % 1000000007;
     
    ans = (ans * i) % 1000000007;
    cout << "Answer using naive method: " << naive_answer << endl;
    cout << "Answer using multiplicative"
         << " modular inverse concept: " << ans;
 
    return 0;
}


Python3
# Python3 program to implement
# the above approach
# To run this code, we need to
# copy modular inverse 
# from below post.
# https://www.geeksforgeeks.org/
# multiplicative-inverse-under-modulo-m/
 
if __name__ == '__main__':
     
    # naive method-calculating the
    # result in a single line
    naive_answer = (((55555 * 55554 *
                      55553 * 55552 *
                      55551) // 120) %
                      1000000007)
 
    ans = 1
 
    # modular_inverse() is a user
    # defined function that calculates
    # inverse of a number
    i = modular_inverse(120, 10000007)
 
    # it will use extended Eucledian
    # algorithm or Fermat's Little
    # Theorem for calculation.
    # MMI of 120 under divison by
    # 1000000007 will be 808333339
    for i in range(5):
        ans = ((ans *
               (55555 - i)) %
                1000000007)
 
    ans = (ans * i) % 1000000007
    print("Answer using naive method:",
           naive_answer)
    print("Answer using multiplicative" +
          "modular inverse concept:", ans)
 
# This code is contributed by himanshu77


C++
#include 
using namespace std;
int main()
{
    long int ans = 1;
    long int mod = (long int)1000000007 * 120;
    for (int i = 0; i < 5; i++)
        ans = (ans * (55555 - i)) % mod;   
    ans = ans / 120;
    cout << "Answer using shortcut: " << ans;
    return 0;
}


Java
class GFG {
 
    public static void main(String[] args)
    {
        long ans = 1;
        long mod = (long)1000000007 * 120;
         
        for (int i = 0; i < 5; i++)
            ans = (ans * (55555 - i)) % mod;
             
        ans = ans / 120;
        System.out.println("Answer using"
                    + " shortcut: "+ ans);
    }
}
 
// This code is contributed by smitha.


Python3
ans = 1
mod = 1000000007 * 120
 
for i in range(0, 5) :
    ans = (ans * (55555 - i)) % mod
     
ans = int(ans / 120)
 
print("Answer using shortcut: ", ans)
 
# This code is contributed by Smitha.


C#
using System;
 
class GFG {
 
    public static void Main()
    {
        long ans = 1;
        long mod = (long)1000000007 * 120;
         
        for (int i = 0; i < 5; i++)
            ans = (ans * (55555 - i)) % mod;
             
        ans = ans / 120;
        Console.Write("Answer using "
                    + "shortcut: "+ ans);
    }
}
 
// This code is contributed by smitha.


PHP


Javascript


Input : 
Output :Answer using naive method: -5973653
        Answer using multiplicative modular inverse concept: 300820513

从上面的示例可以明显看出,幼稚的方法将导致数据溢出,从而导致错误的答案。此外,使用模逆将为我们提供正确的答案。
不使用模乘逆:
但有趣的是,代码的微小变化将放弃寻找模乘乘法逆的使用。

C++

#include 
using namespace std;
int main()
{
    long int ans = 1;
    long int mod = (long int)1000000007 * 120;
    for (int i = 0; i < 5; i++)
        ans = (ans * (55555 - i)) % mod;   
    ans = ans / 120;
    cout << "Answer using shortcut: " << ans;
    return 0;
}

Java

class GFG {
 
    public static void main(String[] args)
    {
        long ans = 1;
        long mod = (long)1000000007 * 120;
         
        for (int i = 0; i < 5; i++)
            ans = (ans * (55555 - i)) % mod;
             
        ans = ans / 120;
        System.out.println("Answer using"
                    + " shortcut: "+ ans);
    }
}
 
// This code is contributed by smitha.

Python3

ans = 1
mod = 1000000007 * 120
 
for i in range(0, 5) :
    ans = (ans * (55555 - i)) % mod
     
ans = int(ans / 120)
 
print("Answer using shortcut: ", ans)
 
# This code is contributed by Smitha.

C#

using System;
 
class GFG {
 
    public static void Main()
    {
        long ans = 1;
        long mod = (long)1000000007 * 120;
         
        for (int i = 0; i < 5; i++)
            ans = (ans * (55555 - i)) % mod;
             
        ans = ans / 120;
        Console.Write("Answer using "
                    + "shortcut: "+ ans);
    }
}
 
// This code is contributed by smitha.

的PHP


Java脚本


输出 :
Answer using shortcut: 300820513

为什么行得通?
仅当分母是分子的因子时,即遵循以下规则的%b = 0时,这才起作用:
如果b | a,那么我们可以将(a / b)%p写为(a%p * b)/ b。
事实证明,此规则对于b的较小值很有用。
让我们考虑一个= x1 * x2 * x3…….xn
我们必须找到ans =(a / b)%1000000007

  1. 令a%(1000000007 * b)的结果为y。为了避免溢出,我们使用模块化乘法属性。这可以表示为
    a =(1000000007 * b)q + y其中y <(1000000007 * b)并且q是整数
  2. 现在将LHS和RHS除以b,我们得到
    y / b = a / b-(1000000007 * b)* q / b
    = a / b -1000000007 * q <1000000007(从1开始)
    因此,y / b等于(a / b)mod(b * 1000000007)。 🙂

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。