非常大的模数素数

时间:2013-07-26 17:42:54

标签: algorithm primes mathematical-optimization largenumber modular-arithmetic

在接受采访时我被问到以下问题:

如何解决这个问题:((3000000!)/(30!)^ 100000)%(任何素数)

我使用蛮力将C程序编码为相同,但我确信他并没有期待这一点。有关解决方案的任何建议吗?

1 个答案:

答案 0 :(得分:1)

3000000! = 1*2*3*4*5*..*8*...*16*...*24*...*32*...40*...*64*...*3000000

我们可以计算结果中 2 的数量吗?是的, 2 的每个幂为每个倍数贡献一个 2 。所以 n 的因子分解中 2 的总数!是n/2 + n/4 + n/8 + n/16 + n/32 + ...,其中/是整数除法,并且术语在大于0时求和:

fnf n f = -- number of `f` factors in `n!`
  sum . takeWhile (>0) . tail . iterate (`div` f) $ n

(编写伪代码in Haskell)。当f*f < n时,将有多个条目进行总结。对于较大的f s,只有一个条目可以求和,即。 n `div` f

因此n!的因子分解为

factfact n =    -- factorization of n! as [ (p,k) ... ] for n! = PROD p_i^k_i
  let
    (ps,qs) = span (\p-> p*p <= n) primes   -- (before, after)
  in
    [(f, fnf n f)   | f <- ps] ++
    [(f, n `div` f) | f <- takeWhile (<= n) qs]

现在, 30 的因子分解!有10个因素:

> factfact 30
[(2,26),(3,14),(5,7),(7,4),(11,2),(13,2),(17,1),(19,1),(23,1),(29,1)]

100000 它的每个因子系数都乘以 100000 。当我们采用 3000000 !的因子分解时,它的总数为216816的前几个术语是:

> factfact 3000000 
[(2,2999990),(3,1499993),(5,749998),(7,499996),(11,299996),(13,249998),
 (17,187497),(19,166665),(23,136361),(29,107142),(31,99998), ... 

所以在除法之后,当我们从第一个中减去第二个时,没有完全没有也没有完全取消:

[(2,399990),(3,99993),(5,49998),(7,99996),(11,99996),(13,49998),
 (17,87497),(19,66665),(23,36361),(29,7142),(31,99998), ...

因此,对于小于3000000的任何素数,余数为0.如果它更大,p > 3000000怎么办?然后,必须使用我们在上面找到的此分解的模幂运算 mod p 和乘法 mod p 。在SO上有很多关于这些的答案。

当然在生产代码中(对于非惰性编程语言)我们不会构建中间分解列表,而只是逐个处理3000000以下的每个素数(没有必要使用惰性语言) )。