最近有一道编程题一直在愁我, 希望有人能帮我一下. - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
YUX
V2EX    问与答

最近有一道编程题一直在愁我, 希望有人能帮我一下.

  •  
  •   YUX
    PRO
    2020-04-04 12:03:02 +08:00 3215 次点击
    这是一个创建于 2027 天前的主题,其中的信息可能已经有所发展或是发生改变。

    题面很简单, 但是我没有在数较大的情况下优化的经验, 所以计算时间较长

    • 有这样一个数列,第一项是 1, 第二项是 3.
    • 递推公式和 fibonacci 数列是一样的, 但有一个额外的条件, 每个数要取模(余数).
    • 例如 mod=127 的前 15 项如下
    i=1,r=1 i=2,r=3 i=3,r=4 i=4,r=7 i=5,r=11 i=6,r=18 i=7,r=29 i=8,r=47 i=9,r=76 i=10,r=123 i=11,r=72 i=12,r=68 i=13,r=13 i=14,r=81 i=15,r=94 
    • 要求的是 f(index,mod) , 给定 index 和 mod, 输出结果
    • 比如 f(10,127)=123, f(6,127)=18

    真正的问题来了, index 和 mod 会是很大的数, 我就懵了.

    请用这个数据检验:

    index = 2**110502 mod = 2**110503-1 f(index,mod)=0 

    目前 python mbp-i9 用时 79.48 秒

    19 条回复    2020-04-04 21:11:07 +08:00
    lance6716
        1
    lance6716  
       2020-04-04 12:05:15 +08:00 via Android
    矩阵乘法计算斐波那契,然后快速幂的优化
    yinsky
        2
    yinsky  
       2020-04-04 12:05:53 +08:00
    动态规划?
    YUX
        3
    YUX  
    OP
    PRO
       2020-04-04 12:08:27 +08:00
    @lance6716 #1 如果先把数列算出来再取模数就太大了, 边算边 mod 数就不会超过 mod
    YUX
        4
    YUX  
    OP
    PRO
       2020-04-04 12:09:47 +08:00
    @yinsky #2 python 的话远超最大递归限制了
    yinsky
        5
    yinsky  
       2020-04-04 12:17:20 +08:00   1
    @YUX 本身类似斐波那契数列就没有啥好的方法,基数太大肯定慢呀,不好搞。
    zh4710jj
        6
    zh4710jj  
       2020-04-04 12:20:10 +08:00 via Android
    斐波那契数列有通项公式的吧,模运算的部分是否可以放到最后再算,最后就是一个大数模 127
    YUX
        7
    YUX  
    OP
    PRO
       2020-04-04 12:24:35 +08:00
    @zh4710jj #6 是有通项公式, 但是公式里有根号 5 这个无理数, 算的时候计算精度不够
    litmxs
        8
    litmxs  
       2020-04-04 12:28:30 +08:00
    矩阵快速幂
    litmxs
        9
    litmxs  
       2020-04-04 12:29:03 +08:00
    gwy15
        10
    gwy15  
       2020-04-04 14:18:10 +08:00   1
    我优化到了在 numba.jit 程度下 1.5s 左右,但是算出来并不是 0 。如果楼主确定这个是 0,那我估计可能是 numba 的问题,我得换 c++ 重新写下
    YUX
        11
    YUX  
    OP
    PRO
       2020-04-04 14:27:57 +08:00 via iPhone
    @gwy15 numba 在 2^64 之后就溢出了
    fx050622
        12
    fx050622  
       2020-04-04 16:45:28 +08:00   1
    我觉得你想复杂了,取模应该不影响 An 的计算的.
    mod(A(n+1))=mod(mod(A(n))*A)
    array=[1,1,1,0]
    我自己 PC 试了下 782736251 次 5.3s

    def multiply(array: Array[Int], times: Int, mode: Int = 127):Unit = {
    if (times > 0) {
    val t1 = array(0)
    val t2 = array(1)
    val t3 = array(2)
    val t4 = array(3)
    array(0) = (t1 + t2) % mode
    array(1) = t1
    array(2) = (t3 + t4) % mode
    array(3) = t3
    multiply(array, times - 1)
    }
    }
    YUX
        13
    YUX  
    OP
    PRO
       2020-04-04 16:49:22 +08:00
    @fx050622 #12 计算我给出的那个数据,用了多少时间? 结果是 0 吧? 谢了
    BiteTheDust
        14
    BiteTheDust  
       2020-04-04 16:54:38 +08:00
    这是一个典型的矩阵快速幂优化线性递推
    当然 也可以直接用 Reeds Sloane 算法
    liyunlong41
        15
    liyunlong41  
       2020-04-04 16:59:09 +08:00 via iPhone
    递推应该可以用矩阵快速幂来优化
    gwy15
        16
    gwy15  
       2020-04-04 17:00:53 +08:00
    用 rust 和 c++ 重新写了一遍,rust 的高精度库实现不太好,还是得用 GMP 。

    复杂度是 log(index) log(mod) log(log(mod)),
    也就是,N=110503 的情况下,N^2 log(N)。算出来是 204e9 数量级,大概就是要一百秒的样子。我用 c++ + GMP 跑出来是 95s,4.0G 主频
    YUX
        17
    YUX  
    OP
    PRO
       2020-04-04 17:03:03 +08:00
    @gwy15 #16 看来是不能再快了,我用的是 python+gmp, 最后结果是 0 吧?
    yuruizhe
        18
    yuruizhe  
       2020-04-04 19:15:58 +08:00
    @YUX 就是 6 楼说的通项公式,公式用二项式定理展开,对根号 5 合并相消,最后应该得到一个整数运算公式
    设 Comb()表述组合数公式
    最后结果应该是[Comb(1,n)*x^0 + Comb(3,n)*x^2 + Comb(5,n)*x^4 + Comb(7,n)*x^6 + ....]/2^n
    superrichman
        19
    superrichman  
       2020-04-04 21:11:07 +08:00 via iPhone
    发现一个有趣的东西,这个数列的值可以这样表达

    2*fibb(x) - fibb(x-1)

    1=2*1-1
    3=2*2-1
    4=2*3-2
    7=2*5-3
    11=2*8-5
    18=2*13-8
    29=2*21-13
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3697 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 04:17 PVG 12:17 LAX 21:17 JFK 00:17
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86