【问题标题】:ACM 4744 Brute-Force AlgorithmACM 4744 蛮力算法
【发布时间】:2012-05-03 10:37:14
【问题描述】:

问题的完整上下文可以在这里看到 Details.

您也可以尝试我的源代码来绘制小数的递归: Pastebin

我正在以数学方式看待这个问题,它是一个嵌套递归,如下所示:

Function Find(integer n, function func)
If n=1
   For i = 1 to a do func()
Elseif n=2
   For i = 1 to b do func()
Else Find(n-1,Find(n-2,func))

Function Main
   Find(n,funny)

我在 Mathematica 中没有模运算的实现是:

$IterationLimit = Infinity
Clear[A]

A [a_, b_, f_, 1] := A [a, b, f, 1, p] = (f a);
A [a_, b_, f_, 2] := A [a, b, f, 2, p] = (f b);
A [a_, b_, f_, n_] := 
A [a, b, f, n, p] = (A[a, b, A[a, b, f, n - 2], n - 1]);

这揭示了一般 ab

的一些不错的输出
A[a, b, funny, 1]
a funny
A[a, b, funny, 2]
b funny
A[a, b, funny, 3]
a b funny
A[a, b, funny, 4]
a b^2 funny
A[a, b, funny, 5]
a^2 b^3 funny
A[a, b, funny, 6]
a^3 b^5 funny

所以当我们查看 Func 被调用的频率时,它看起来像 a^(F(n)) * b^(F(n+1)) F(n) 作为第 n 个斐波那契数。所以我的问题是:我如何获得非常大的斐波那契数模 p,我对此做了很多研究,通读了斐波那契的周期长度,尝试了一些递归:

F(a+b) = F(a+1) * F(b) + F(a)*F(b-1)

但似乎递归深度 (log_2(1.000.000.000) ~=30 ) 将 p 拆分为两个数字时要多得多,即使是深度第一次递归也是如此。

a= floor(n/2)
b= ceiling(n/2)

当我有斐波数时,乘法和求幂 在我看来应该不是问题。

很遗憾没有:/

我仍然遇到问题。首先计算指数中的斐波那契数并没有正确解决问题,这是我在那里应用的错误数学公式:/

所以我想到了其他计算公式的方法:

(a^(Fibonacci(n-2))*b^(Fibonacci(n-1))) mod p

但是随着斐波那契数变得非常大,我假设必须有一种比计算整个斐波那契数然后使用 BigInteger/BigFloat 应用离散指数函数更简单的方法。有人对我有提示吗,我看不到进一步的进展。谢谢

所以这就是我目前为止的地方,可能只是我缺少的一个小东西,所以期待你的回复

谢谢

【问题讨论】:

    标签: math functional-programming nested-loops fibonacci


    【解决方案1】:

    如果是关于计算斐波那契数,则有一个非递归、非迭代的公式。它在荷兰维基百科关于斐波那契数的页面上很突出,但在英文页面上却没有那么多。

    F(n) = ( ( 1 + sqrt(5) ) ^ n - ( 1- sqrt(5) ) ^ n ) / (2 ^ n * sqrt(5))

    http://upload.wikimedia.org/wikipedia/nl/math/1/7/4/1747ee745fbe1fbf10fb3d9de36b8927.png

    来源:http://nl.wikipedia.org/wiki/Rij_van_Fibonacci

    也许你可以用这个公式做点什么。

    【讨论】:

    • 是的,这是我的想法之一,Mathematica 解决它没有问题,但是在 Java 中,我认为不可能将这个数字存储为,比如说,双倍。而且我不知道 Mathematica 是如何快速计算这些数字的。对于大数字,甚至有一个概括,因为最后一项限制为零。谢谢
    【解决方案2】:

    您可能会发现我对计算Fibonacci and Lucas numbers 的各种方法的思考很有帮助。在那里,我展示了如何使用基本上为 O(log2(n)) 的递归方案进行计算。它非常适用于大型斐波那契数。而且,如果您将所有这些都以某个小数为模,您甚至不需要使用大整数工具进行计算。即使是巨大的斐波那契数字,这也将是非常快的。下面这个只是中等大小。

    fibonacci(10000)
    ans =
        33644764876431783266621612005107543310302148460680063906564769974680
    081442166662368155595513633734025582065332680836159373734790483865268263
    040892463056431887354544369559827491606602099884183933864652731300088830
    269235673613135117579297437854413752130520504347701602264758318906527890
    855154366159582987279682987510631200575428783453215515103870818298969791
    613127856265033195487140214287532698187962046936097879900350962302291026
    368131493195275630227837628441540360584402572114334961180023091208287046
    088923962328835461505776583271252546093591128203925285393434620904245248
    929403901706233888991085841065183173360437470737908552631764325733993712
    871937587746897479926305837065742830161637408969178426378624212835258112
    820516370298089332099905707920064367426202389783111470054074998459250360
    633560933883831923386783056136435351892133279732908133732642652633989763
    922723407882928177953580570993691049175470808931841056146322338217465637
    321248226383092103297701648054726243842374862411453093812206564914032751
    086643394517512161526545361333111314042436854805106765843493523836959653
    428071768775328348234345557366719731392746273629108210679280784718035329
    131176778924659089938635459327894523777674406192240337638674004021330343
    297496902028328145933418826817683893072003634795623117103101291953169794
    607632737589253530772552375943788434504067715555779056450443016640119462
    580972216729758615026968443146952034614932291105970676243268515992834709
    891284706740862008587135016260312071903172086094081298321581077282076353
    186624611278245537208532365305775956430072517744315051539600905168603220
    349163222640885248852433158051534849622434848299380905070483482449327453
    732624567755879089187190803662058009594743150052402532709746995318770724
    376825907419939632265984147498193609285223945039707165443156421328157688
    908058783183404917434556270520223564846495196112460268313970975069382648
    706613264507665074611512677522748621598642530711298441182622661057163515
    069260029861704945425047491378115154139941550671256271197133252763631939
    606902895650288268608362241082050562430701794976171121233066073310059947
    366875
    

    诀窍很简单。只需将第 2 个斐波那契数和卢卡斯数与第 n 个这样的数关联起来。它允许我们向后工作。所以要计算 F(n) 和 L(n),我们需要知道 F(n/2) 和 L(n/2)。显然,只要 n 是偶数,这就会起作用。对于奇数 n,有类似的方案可以让我们递归地向下移动。

    为了好玩,我只是修改了上面的工具,接受一个模数。因此,要计算索引为 1e15 的斐波那契数的最后 6 位数字,大约需要 1/6 秒。

    tic,[Fn,Ln] = fibonacci(1e15,1000000),toc
    Elapsed time is 0.161468 seconds.
    
    Fn =
        546875
    
    Ln =
        328127
    

    注意:在我讨论递归计算斐波那契数时,我确实对所需的递归调用次数做了一些计算。看到这个数字确实与斐波那契数列本身非常相关。这很容易推导出来。

    【讨论】:

    • 在此先感谢,我会看看它,但也许这些提示足以让我自己深入研究。我希望我能理解基本的matlab语言,但它似乎和所有函数式编程语言一样:)
    猜你喜欢
    • 2015-06-22
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 2016-04-05
    相关资源
    最近更新 更多