Algorithm 是否需要有关mod 100000007问题的帮助

Algorithm 是否需要有关mod 100000007问题的帮助,algorithm,math,language-agnostic,Algorithm,Math,Language Agnostic,我数学很差,总是被那些需要以素数为模的答案所困扰 例:(500!/20!)模100000007 我熟悉大整数,但在计算500的阶乘(即使使用DP)后计算模似乎需要花费大量时间 我想知道是否有一种特殊的方法来处理这类问题 我目前正试图解决这样一个问题: 如果有人能告诉我一个教程或一种处理这些编码问题的方法,那将非常有帮助。 我熟悉java和C++,,这些大数模任务的关键不是在执行模数之前计算完整的结果。strong>您应该在中间步骤中降低模数,以保持较小的数值: 500! / 20! = 21

我数学很差,总是被那些需要以素数为模的答案所困扰

例:(500!/20!)模100000007

我熟悉大整数,但在计算500的阶乘(即使使用DP)后计算模似乎需要花费大量时间

我想知道是否有一种特殊的方法来处理这类问题

我目前正试图解决这样一个问题:

如果有人能告诉我一个教程或一种处理这些编码问题的方法,那将非常有帮助。
我熟悉java和C++,

,这些大数模任务的关键不是在执行模数之前计算完整的结果。strong>您应该在中间步骤中降低模数,以保持较小的数值:

500! / 20! = 21 * 22 * 23 * ... * 500

21 * 22 * 23 * 24 * 25 * 26 * 27 = 4475671200

4475671200 mod 1000000007 = 475671172
475671172 * 28 mod 1000000007 = 318792725
318792725 * 29 mod 1000000007 = 244988962
244988962 * 30 mod 1000000007 = 349668811

...

 31768431 * 500 mod 1000000007 = 884215395

500! / 20! mod 1000000007 = 884215395
你不需要在每一步都降低模量。只要经常这样做就可以避免数量过大



请注意,
long
的最大值为2^63-1。因此,在两个正整数值(即其中一个操作数为
long
)之间执行64位乘法不会溢出
long
。您可以安全地执行余数操作
%
(如果也是正数),并在需要时返回整数。

首先观察
500/20!
是21到500(包括21到500)之间所有数字的乘积。接下来,请注意,您可以逐项执行模乘运算,每次运算结束时取
%100000007
。你现在应该可以写你的程序了。小心不要使数字溢出:32位可能不够

我想这对你有点用处

for(mod=prime,res=1,i=20;imod)//检查数字是否超过mod
res%=mod;//以避免模运算,因为它是昂贵的操作
}

在大多数编程竞赛中,我们需要以10^9+7的模回答结果。这背后的原因是,如果问题约束是大整数,只有高效的算法才能在允许的有限时间内解决它们。

什么是模运算:
对两个操作数进行除法运算后得到的余数称为模运算。进行模数运算的运算符为“%”。例如:a%b=c,这意味着,当a除以b时,得到余数c,7%2=1,17%3=2。
为什么我们需要模:

500! / 20! = 21 * 22 * 23 * ... * 500

21 * 22 * 23 * 24 * 25 * 26 * 27 = 4475671200

4475671200 mod 1000000007 = 475671172
475671172 * 28 mod 1000000007 = 318792725
318792725 * 29 mod 1000000007 = 244988962
244988962 * 30 mod 1000000007 = 349668811

...

 31768431 * 500 mod 1000000007 = 884215395

500! / 20! mod 1000000007 = 884215395
  • 采用Mod的原因是为了防止整数溢出。C/C++中最大的整数数据类型是无符号长整型,它是64位的,可以处理从0到(2^64–1)的整数。但在一些产出增长率很高的问题上,这种高范围的无符号多头可能是不够的。 假设在一个64位变量“a”中存储了2^62,在另一个64位变量“B”中存储了2^63。当我们将A和B相乘时,系统不会给出运行时错误或异常。它只是执行一些伪计算并存储伪结果,因为结果的位大小是在乘法溢出之后出现的

  • 在一些问题中,需要计算结果的模逆,而这个数很有帮助,因为它是素数。此外,这个数字应该足够大,否则模块化逆技术在某些情况下可能会失败。
    由于这些原因,问题解决者要求给出某个数的模的结果N
    N的值取决于某些标准:

  • 它应该足够大以适应最大的整数数据类型,即确保结果中没有溢出

  • 它应该是一个素数,因为如果我们用素数对一个数进行mod,结果通常是间隔的,即结果与用非素数对该数进行mod的结果非常不同,这就是为什么素数通常用于mod。
    10^9+7符合这两个标准。它是前10位素数,也适用于int数据类型。事实上,任何小于2^30的素数都可以防止可能的溢出。
    如何使用模:
    模的几个分配性质如下:

  • (a+b)%c=((a%c)+(b%c))%c

  • (a*b)%c=((a%c)*(b%c))%c

  • (a-b)%c=((a%c)-(b%c))%c

  • (a/b)%c=((a%c)/(b%c))%c

    所以,模在+、*和–上是分布的,但在/[请参考除法了解详细信息] 注意:(a%b)的结果将始终小于b。 在计算机程序的情况下,由于变量限制的大小,我们在每个中间阶段执行模M,这样就不会发生范围溢出

  • 使用模在不同位置查找大数阶乘的函数


    参考资料:

    谢谢您的回答。你能再帮我一个疑问吗。如何确保eg:31768431*x(对于任何x)不会超出long的范围。如果
    long
    的最大值为2^63-1,那么
    1768431*x
    只要
    x<290331368171
    就不会溢出。但是比较操作不是同样昂贵吗?@nikhil你指的是什么比较操作?比较操作本身很便宜。在你需要减少之前,确定你能做多少倍是有点棘手的。(粗略地说,当乘积增长时,您需要跟踪它的位长度。)但您总是可以默认在每次乘法后降低模。