V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
czheo
V2EX  ›  问与答

问一算法题

  •  
  •   czheo · 2014-12-14 21:35:03 +08:00 · 2788 次点击
    这是一个创建于 3631 天前的主题,其中的信息可能已经有所发展或是发生改变。

    输入:
    5个整数
    A, B, X1, K, M

    有一个random算法
    Xn = (A * Xn-1 + B) % M

    要输出第K到K+4的X结果

    老老实实写了如下python代码,问如何优化?
    ~~~
    A, B, X1, K, M = map(int, raw_input().split())

    def myRand(seed):
    return (A * seed + B) % M

    seed = X1
    for i in xrange(1, K+5):
    if i > K-1:
    print seed
    seed = myRand(seed)
    ~~~

    15 条回复    2014-12-15 18:50:36 +08:00
    jiang42
        1
    jiang42  
       2014-12-14 21:55:21 +08:00
    不知道你想怎么优化?我能想到的就是map换成list comprehension。或者数学好的话把递归表达式直接写成直接求值的表达式。一般来说,O(n)的算法在实际生活中已经足够好了
    czheo
        2
    czheo  
    OP
       2014-12-14 22:05:39 +08:00
    我把代码提交上去,系统说运行超时,我只能想出O(n)的算法。不知道考点在哪里。
    hint: 比如M极小的时候除余会不会变慢?

    @jiang42 把递归表达式直接写成直接求值要怎么写?
    iloahz
        3
    iloahz  
       2014-12-14 22:24:24 +08:00 via iPhone
    可以写出来通项公式的样子,要是嫌麻烦用矩阵也行噻
    czheo
        4
    czheo  
    OP
       2014-12-14 22:26:53 +08:00
    一软件公司出题让我求通项公式也太....

    @iloahz 怎么个矩阵法?
    akagi
        5
    akagi  
       2014-12-14 22:37:04 +08:00
    同余吧 循环节是M 打个表出来 直接到里面取 —— 简单想了下 不一定对
    akagi
        6
    akagi  
       2014-12-14 22:39:04 +08:00
    好像不太对…… 再想想去
    iloahz
        7
    iloahz  
       2014-12-14 22:58:48 +08:00 via iPhone
    @akagi 对的呀,线性递推取模肯定是有循环节的,当M比较小的时候妥妥可以

    @czheo 求通项又不是很麻烦啊,矩阵就是
    [1, X1] * [1, B \n 0, A] ^ (n -1) = [1, Xn]嘛,如果你这么鄙视软件公司…那没准就是递推优化优化吧
    jiang42
        8
    jiang42  
       2014-12-14 23:00:57 +08:00
    @czheo 可以提供提交的地址么?我去试试

    组合数学,用母函数应该可以
    akagi
        9
    akagi  
       2014-12-15 00:26:02 +08:00
    @iloahz 不过考虑到随机数发生器的场景,M通常比较大就是了。

    计算时还是通项比较靠谱,
    x_2 = a * x_1 + b;
    x_3 = a^2 * x_1 + b * a + b;
    ...
    x_k = [ a^k-1 * x_1 + b * (1+a+a^2+...) ];
    最后取个余得到结果,前面没影响。另外计算 (a^k-1)%M 和 右侧等比数列 可以用点小技巧,差不多这样。
    whalegia
        10
    whalegia  
       2014-12-15 04:28:24 +08:00
    是这样吗?……
    https://gist.github.com/whaleee/4a2ae06b6e5ef348c06c

    这个输入数字大小有限制吗?感觉这么写没法处理很大的输入……
    czheo
        11
    czheo  
    OP
       2014-12-15 07:50:01 +08:00
    @akagi 通项不对吧,怎么证明最后求余和每步求余结果一样?
    whalegia
        12
    whalegia  
       2014-12-15 08:20:34 +08:00
    其实我也觉得同项不太对
    whalegia
        13
    whalegia  
       2014-12-15 08:27:15 +08:00
    但是我觉得答案里是有循环的,搞个 list 记录一下循环吧?

    我去试试
    akagi
        14
    akagi  
       2014-12-15 09:13:13 +08:00
    @czheo


    y_n = k * M + c;
    y_(n+1) = A * (k * M + c) + B;
    y_(n+2) = A^2 * (k * M + c) + A * B + B;
    =>
    x_n = c;
    x_(n+1) = (A * x_n + B) % M;
    x_(n+2) = (A * [(A * x_n + B) % M] + B) % M = ...

    核心在于求余满足分配率。
    czheo
        15
    czheo  
    OP
       2014-12-15 18:50:36 +08:00 via iPhone
    akagi 百度说求余不符合分配律
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2811 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 13:59 · PVG 21:59 · LAX 05:59 · JFK 08:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.