Algorithm 是否需要有关mod 100000007问题的帮助
我数学很差,总是被那些需要以素数为模的答案所困扰 例:(500!/20!)模100000007 我熟悉大整数,但在计算500的阶乘(即使使用DP)后计算模似乎需要花费大量时间 我想知道是否有一种特殊的方法来处理这类问题 我目前正试图解决这样一个问题: 如果有人能告诉我一个教程或一种处理这些编码问题的方法,那将非常有帮助。Algorithm 是否需要有关mod 100000007问题的帮助,algorithm,math,language-agnostic,Algorithm,Math,Language Agnostic,我数学很差,总是被那些需要以素数为模的答案所困扰 例:(500!/20!)模100000007 我熟悉大整数,但在计算500的阶乘(即使使用DP)后计算模似乎需要花费大量时间 我想知道是否有一种特殊的方法来处理这类问题 我目前正试图解决这样一个问题: 如果有人能告诉我一个教程或一种处理这些编码问题的方法,那将非常有帮助。 我熟悉java和C++,,这些大数模任务的关键不是在执行模数之前计算完整的结果。strong>您应该在中间步骤中降低模数,以保持较小的数值: 500! / 20! = 21
我熟悉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的值取决于某些标准:
10^9+7符合这两个标准。它是前10位素数,也适用于int数据类型。事实上,任何小于2^30的素数都可以防止可能的溢出。
如何使用模:
模的几个分配性质如下:
所以,模在+、*和–上是分布的,但在/[请参考除法了解详细信息] 注意:(a%b)的结果将始终小于b。 在计算机程序的情况下,由于变量限制的大小,我们在每个中间阶段执行模M,这样就不会发生范围溢出
参考资料:谢谢您的回答。你能再帮我一个疑问吗。如何确保eg:31768431*x(对于任何x)不会超出long的范围。如果
long
的最大值为2^63-1,那么1768431*x
只要x<290331368171
就不会溢出。但是比较操作不是同样昂贵吗?@nikhil你指的是什么比较操作?比较操作本身很便宜。在你需要减少之前,确定你能做多少倍是有点棘手的。(粗略地说,当乘积增长时,您需要跟踪它的位长度。)但您总是可以默认在每次乘法后降低模。