最大素因子c语言,003. 最大素因子

题目

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?

解答

这道题目很简单,就是要我们找出 600,851,475,143 的最大素因数。来看看我们的 Haskell 程序吧:

factors 1 = []

factors n = let p = head [ x | x

main = print $ last $ factors 600851475143

上述程序中:

factors 函数返回其自变量的所有(从小到大排列的)素因数的列表。

第 1 行处理边界情况,整数 1 没有素因数,返回一个空列表。

第 2 行处理大于 1 的整数 n,从 2 开始逐个测试,遇到第一个能够整除 n 的数(这个数一定是素数)就停止,然后递归调用自身处理 n/p 。

第 3 行的 main 函数输出 600,851,475,143 的素因数列表的最后一个元素,就是我们要的答案。

改进

每次都从 2 开始逐个测试是没有必要的,完全可以从上次结束的地方开始测试:

factors = flip fact 2

fact 1 _ = []

fact n k = let p = head [ x | x

main = print $ last $ factors 600851475143

上述程序中:

第 2 行至第 3 行的 fact 函数要求两个自变量,第一个是待分解的整数,第二个是测试的起始位置。递归调用自身时从刚刚分解出来的素因数开始。

第 1 行的 factors 函数简单地调用 fact 函数(将其第二个自变量置为 2)。flip 函数用于对调 fact 函数的两个自变量。当然,第 1 行改为 factors n = fact n 2 也是可以的。

再次改进

由于 2 是唯一的偶素数,因此我们可以先分解出所有的素因数 2,然后就可以只测试奇数了:

factors n = if even n then 2 : factors (div n 2) else fact n 3

fact 1 _ = []

fact n k = let p = head [ x | x

main = print $ last $ factors 600851475143

上述程序中:

第 1 行的 factors 函数判断其自变量 n 是否为偶数,如是,则不断递归调用自身,分解出所有的素因数 2。如果 n 为奇数,则调用 fact 函数处理,注意这次测试的起始位置是 3 。

第 2 行至第 3 行的 fact 函数和前一个程序基本相同,除了只测试奇数以外。

最终的改进

由于整数 n 最多只能有一个素因数大于

efb1a34e9a05ba311cf46a700f55426d.png,我们可以相应设置测试的上限:

factors n = if even n then 2 : factors (div n 2) else fact n 3

fact 1 _ = []

fact n k = if null xs then [n] else let p = head xs in p : fact (div n p) p

where xs = [ x | x

main = print $ last $ factors 600851475143

上述程序中:

第 4 行通过 ceiling $ sqrt $ fromIntegral n 将列表的上限设置为

ab730a4dbb62aa4f3b7f61872ae3a55b.png,注意此时列表可能为空,表示要测试的数已经超过

efb1a34e9a05ba311cf46a700f55426d.png 了。

第 3 行要判断列表是否为空,如是,则此时 n 一定是素数,直接将 n 放入素因数列表中返回即可。

程序的其余部分和上一个程序相同。

注意,前面几个程序要测试的数的列表虽然是无限列表,但实际上等效于上限为 n 的列表。因为列表推导式中的条件 mod n x == 0,当 x 增加到 n 时一定会成立(虽然 x 可能没有增加到 n 程序就终止了,但 x 一定不会超过 n)。

详细的论述请参见:003_overview.pdf 。这些程序对小整数来说都足够快了,但是对大整数则太慢了。

进阶

将大整数分解为素因数的乘积是一项非常困难的工作,目前最有效的方法是数域筛法,可参阅科学出版社 2009 年出版的《整数分解》一书。我在图灵社区写了一篇《整数分解》读书笔记。将下面这个整数分解为素因数的乘积,就可获得 20 万美元的奖金。有谁想试一下的?

RSA-2048 has 617 decimal digits (2,048 bits). It is the largest of the RSA numbers and carried the largest cash prize for its factorization, US$200,000. The largest factored RSA number is 768 bits long (232 decimal digits), and the RSA-2048 may not be factorizable for many years to come, unless considerable advances are made in integer factorization or computational power in the near future.

RSA-2048 =

2519590847565789349402718324004839857142928212620403202777713783604366202070

7595556264018525880784406918290641249515082189298559149176184502808489120072

8449926873928072877767359714183472702618963750149718246911650776133798590957

0009733045974880842840179742910064245869181719511874612151517265463228221686

9987549182422433637259085141865462043576798423387184774447920739934236584823

8242811981638150106748104516603773060562016196762561338441436038339044149526

3443219011465754445417842402092461651572335077870774981712577246796292638635

6373289912154831438167899885040445364023527381951378636564391212010397122822

120720357

750597cc9bdaaeab89f7aec6109888a9.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值