近似平方除数,在中间相遇

2016年9月6日

在我们看代码之前,让我们看一个例子,这样我们一定会在脑海中清楚地确定算法;我们计算了360的近似平方因子=2*2*2*3*5。有六个因子,所以我们把它们分成两半并计算它们的除数:下半部是因子2、2和2,除数是1、2、4和8,上半部是因数3、3和5,除数为45、15、9、5、3和1,降序排列。360的平方根约为18.973666,因此近似平方因子的上限为18。

现在我们迭代了中间相遇算法。我们反复将低除数列表的头乘以高除数列表中的头。如果乘积超过了极限,我们就丢弃高分除数列表的头。否则,在首先检查乘积是否为新的最大值之后,我们将丢弃低除数列表的头部。该表以相反的顺序显示索引、当前最大值、低除数和高除数:

0  0 (1 2 4 8) (45 15 9 5 3 1)1  0 (1 2 4 8) (15 9 5 3 1)2 15 (2 4 8)   (15 9 5 3 1)3 15 (2 4 8)   (9 5 3 1)4 18 (4 8)     (9 5 3 1)5 18 (4 8)     (5 3 1)6 18 (4 8)     (3 1)7 18 (8)       (3 1)8 18 (8)       (1)9 18 ()        (1)

第0行显示初始状态,当前最大值为0,还有两个除数列表。第一个计算取1×45=45,这超出了限制,所以第1行显示45从高除数列表中删除。第二次计算取1×15=15,这没有超出限制,因此第2行显示了一个新的最佳值15,并从低除数列表中删除了1。第三次计算取2×15=30,这超出了限制,因此从高除数列表中删除了15。第四次计算取2×9=18,这没有超出限制,所以我们保存新的最佳值,并从低除数列表中删除2。以此类推,在低除数列表用完后停止,最终的解是18。注意360有24个除数,但只使用了9个(除数1使用了两次);除数6、10、12、18、20、24、30、36、40、60、72、90、120、180和360从未出现。

现在我们可以看看我们的Hofstra解决方案版本:

(定义(nsd n)(让*((极限(isqrt n))(fs(系数n))(中位数(商(长度fs)2))(los(除数(适用*(取中间fs)))(his(reverse(除数(apply*(drop-mid-fs)))))(let loop(最佳0)(los los)(他的his))(如果(或(空?los)(空?his))最好(出租)(cond((<极限t)(循环最佳los(cdr-his)))((<最佳t)(循环t(cdr-los)his))(其他(loop best(cdr los)his))))>(时间(nsd(应用*(素数190)))(时间(nsd(应用*…))67件藏品2.066603685秒的cpu运行时间,包括0.950848951秒的采集2.072700979s已过实时,包括0.954510719s采集分配了626128608字节,包括回收的601787408字节2323218950659046189161096883702440585

这相当快,即使在n个有大量因素(这是一种相对罕见的情况)。第一,n个必须考虑因素,这可能是算法的难点。然后创建两个除数列表。迭代在每个步骤中删除一个除数,最多执行两次比较。解决Euler项目266在我的机器上大约需要2秒钟。斯隆序列A060798型找到基本元素的近似平方因子:

(定义(原始nsd n)(让(第1页))(do((ps(素数n)(cdr-ps))(i 1(+i 1))((空?ps))(set!p(*p(car ps))(显示i)(显示“:”)(显示(nsd p))(换行))>(primorial-nsd 190)1: 12: 23: 54:145:426: 1657: 7148: 30949: 1485810: 7953411: 44705112: 271469013: 1739507014: 11437107015: 78315207016: 570858733517: 4384809300318: 34244465809419: 280311989618520: 2361954086373021: 20181398110261522: 179377929363343723: 1634205096456564524: 15417092601343032625: 151840917758102436526: 1525982512072283747827: 15487032971503871365928: 160199108815498917425829: 1672527898589895745469530: 17779216353813412443289531: 200361596340149943023401732: 2293243289780792850424693033: 26841724482517378826457579834: 316459264233871203498694558535: 3862877620294957867897420841036: 47467834876802536593200417654737: 594770266456337929196331498162938: 7593518429320535824994315774363139: 98129884369575627849882045799190540: 1290697113140835984047465878221416541: 17268350464373279388577815865066917842: 2323218950659046189161096883702440585

您可以在以下位置运行程序网址:http://ideone.com/V0KZDB,您还将看到使用的辅助功能。

页:1 2

对“近似平方除数,在中间相遇”的一种回应

  1. 我会遇到这种解决问题的方法,但不得不说,我对它比分支绑定的速度快得多印象深刻。

    模拟退火解决方案如何?

留下评论