我在数学上很弱,总是遇到需要回答模数的问题。
例如:(500!/ 20!)mod 1000000007
我熟悉BigIntegers但计算因子500后计算模数(即使在使用DP之后)似乎需要花费很多时间。
我想知道是否有一种接近/处理这类问题的特殊方法。
这是我目前要解决的一个问题: http://www.codechef.com/FEB12/problems/WCOUNT
如果有人可以指导我处理这些编码问题的教程或方法,那将会非常有用。 我熟悉Java和C ++。
答案 0 :(得分:51)
这些大数模数任务的关键是在执行模数之前不计算完整结果。 您应该减少中间步骤中的模数以保持数字小:
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.因此,在两个正整数值之间执行64位乘法(即其中一个操作数是long
)将不会溢出{{ 1}}。您可以安全地执行余数操作long
(如果这也是正数)并在需要时强制转换为整数。
答案 1 :(得分:7)
首先观察500!/20!
是21到500之间所有数字的乘积,然后观察您可以逐项执行模乘,在每次操作结束时取%1000000007
。你现在应该可以编写程序了。注意不要溢出数字:32位可能不够。
答案 2 :(得分:5)
我认为这可能会对您有所帮助
for(mod=prime,res=1,i=20;i<501;i++)
{
res*=i; // an obvious step to be done
if(res>mod) // check if the number exceeds mod
res%=mod; // so as to avoid the modulo as it is costly operation
}
答案 3 :(得分:0)
在大多数编程比赛中,我们都需要以10 ^ 9 + 7模的方式回答结果。这背后的原因是,如果问题约束是大整数,则只有高效的算法才能在允许的有限时间内解决它们。
什么是模运算:
在两个操作数上进行除法运算后获得的余数称为模运算。进行模运算的运算符为“%”。例如:a%b = c,这意味着,当a除以b时,将得到余数c,7%2 = 1、17%3 =2。
我们为什么需要取模:
采用Mod的原因是为了防止整数溢出。 C / C ++中最大的整数数据类型是64位无符号long long int,可以处理从0到(2 ^ 64 – 1)的整数。但是在某些产出增长率很高的问题中,这种高范围的无符号长久可能不足。 假设在64位变量“ A”中存储了2 ^ 62,在另一个64位变量“ B”中存储了2 ^ 63。当我们将A和B相乘时,系统不会给出运行时错误或异常。它只是进行一些伪计算并存储伪结果,因为结果的位大小是在乘法溢出之后得出的。
在某些问题中,需要计算模逆的结果,并且该数字很有用,因为它是质数。同样,这个数字应该足够大,否则模块化逆向技术在某些情况下可能会失败。
由于这些原因,问题解决者需要给出一些 N 取模的结果。
N的值取决于某些条件:
它应该足够大以适合最大的整数数据类型,即确保没有结果溢出。
它应该是质数,因为如果我们将质数取为质数,则结果通常是隔开的,即与非质数的质数相比,结果是非常不同的结果,这就是质数为通常用于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
因此,模是分布在+,*和–上,而不是分布在/ [有关详细信息,请参考Modular除法]
注意:(a%b)的结果将始终小于b。
对于计算机程序,由于变量限制的大小,我们在每个中间阶段执行模M,以使范围溢出永远不会发生。
Example: a = 145785635595363569532135132 b = 3151635135413512165131321321 c = 999874455222222200651351351 m = 1000000007 Print (a*b*c)%m. Method 1: First, multiply all the number and then take modulo: (a*b*c)%m = (459405448184212290893339835148809 515332440033400818566717735644307024625348601572) % 1000000007 a*b*c does not fit even in the unsigned long long int due to which system drop some of its most significant digits. Therefore, it gives the wrong answer. (a*b*c)%m = 798848767 Method 2: Take modulo at each intermediate steps: i = 1 i = (i*a) % m // i = 508086243 i = (i*b) % m // i = 144702857 i = (i*c) % m // i = 798848767 i = 798848767 Method 2 always gives the correct answer.
使用模但在不同位置查找大量阶乘的函数。