需要帮助mod 1000000007的问题

时间:2012-02-07 00:03:04

标签: algorithm math language-agnostic

我在数学上很弱,总是遇到需要回答模数的问题。

例如:(500!/ 20!)mod 1000000007

我熟悉BigIntegers但计算因子500后计算模数(即使在使用DP之后)似乎需要花费很多时间。

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

这是我目前要解决的一个问题: http://www.codechef.com/FEB12/problems/WCOUNT

如果有人可以指导我处理这些编码问题的教程或方法,那将会非常有用。 我熟悉Java和C ++。

4 个答案:

答案 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的值取决于某些条件:

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

  2. 它应该是质数,因为如果我们将质数取为质数,则结果通常是隔开的,即与非质数的质数相比,结果是非常不同的结果,这就是质数为通常用于mod。
    10 ^ 9 + 7满足两个条件。它是前10位素数,也适合int数据类型。实际上,任何小于2 ^ 30的质数都可以,以防止可能的溢出。
    如何使用模数:
    模的一些分布特性如下:

  3. (a + b)%c =((a%c)+(b%c))%c

  4. (a * b)%c =((a%c)*(b%c))%c

  5. (a – b)%c =((a%c)–(b%c))%c

  6. (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.

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

参考:https://www.geeksforgeeks.org/modulo-1097-1000000007/