【问题标题】:Efficient solution for my task needed我的任务需要有效的解决方案
【发布时间】:2014-09-04 06:54:56
【问题描述】:

我只是解决了这个问题,但想知道更有效的矩阵乘法方法

 M = | 1 0 3 |
     | 1 0 2 |
     | 0 5 0 |

f[n] = M^n

我已经使用Exponentiation_by_squaring实现了

还有比这更有效的吗?

【问题讨论】:

  • @DavidPostill 为什么选择 OT?优化和性能是这里的常见标签。
  • 我猜,这实际上更适合数学,因为有一个封闭形式的解决方案。另一种可能性:您可以通过推导两个步骤的公式来两次加速程序。这可以重复......
  • @DavidPostill 其他人会将其发送给 CR。如果你问我,这都是 BS。
  • @maaartinus 你说得对,我应该说 codereview(咖啡不够)
  • @maaartinus Others would send it to CR. It's all BS, if you ask me. ??正在进行什么讨论..不能让你

标签: java performance algorithm dynamic-programming


【解决方案1】:

我想,这实际上更适合数学,因为有一个封闭形式的解决方案。是Linear homogeneous recurrence relations with constant coefficients的系统。

另一种可能性:您可以通过导出两个步骤的公式来两次加速程序,即通过RR(i-2)等表达RR(i)等。

这可以重复,所以你可以跳得更快。

【讨论】:

    【解决方案2】:

    一个问题是您的计算溢出了。如果你在 K=1 和 J=9 的情况下运行它,你会得到 -334328541#510576792#-817751931
    最简单的解决方法是在calculateProduction 中执行% 1000000006

    关于效率,我会将此问题视为执行矩阵乘法。 你从向量开始(即 1*3 矩阵):

    3 1 0
    

    并且在每一步都将它(mod 1000000006)与矩阵相乘:

    1 1 0
    0 0 5
    3 2 0
    

    我们称向量V和矩阵M。基本上你需要计算V*MN。由于矩阵乘法是关联的,您可以先计算 MN,然后递归执行:
    MN = (MN/2)2 如果 N 是偶数,或者
    MN = M*(M[N/2])2 如果 N 是奇数

    【讨论】:

    • 我也尝试过..但没有得到建议
    • 是的,我已经想到了这个算法,但是问题矩阵求幂可能需要时间..你能更好地了解矩阵求幂算法吗..(动态规划)
    • @ankit337 我已经解释了如何轻松地进行矩阵求幂,您阅读我答案的最后一部分了吗?
    • 嗯,我明白了,但我认为这不足以提高性能,我得到了最好的方法qc.edu.hk/math/Teaching_Learning/…,如何实现这个?
    • @ankit337 我很确定我的方法足够好,它是对数时间
    【解决方案3】:

    您不需要计算 MM。这就是为什么:

    PP[i] = 5*MM[i-1] = 5*(RR[i-2] + 2*PP[i-2])
    RR[i] = RR[i-1] + 3*PP[i-1] = (RR[i-2] + 3*PP[i-2]) + 3*PP[i-1]
    

    看到了吗?您不需要在每一步都计算 MM。这应该是算法:

    public class RecurrenceMachine {
        private static final int max = 1000000006;
    
        public String calculate(int k, int j) {
            long n = k * j;
            if (n < 1)
                return "error";
            long RRi2 = 3;
            long PPi2 = 0;
            long RRi1 = 3 + 3 * PPi2;
            long PPi1 = 5 * 1;
            if (n == 1)
                return RRi1 + "##" + (RRi2 + 2 * PPi2) + "##" + PPi1;
            Long PPi = (long) 0, RRi = (long) 0, temp;
            int i;
            for (i = 2; i <= n; i++) {
                temp = RRi2 + 2 * PPi2;
                PPi = 5 * temp;
                if (PPi >= max)
                    PPi %= max;
                RRi = temp + PPi2 + 3 * PPi1;
                if (RRi >= max)
                    RRi %= max;
                RRi2 = RRi1;
                PPi2 = PPi1;
                RRi1 = RRi;
                PPi1 = PPi;
            }
            return RRi + "##" + (RRi2 + 2 * PPi2) % max + "##" + PPi1;
        }
    }
    

    我只尝试了较小的值,它似乎有效。

    【讨论】:

    • 感谢您的解决方案。您已经在一个级别上改进了代码,但对于大量输入,它与我的代码几乎相同。
    • @ankit337 你能给我一些大的投入,让我自己试试吗?
    • 当然 .. 这里的条件是1&lt;= K,J &lt;= 10^6 所以你可以从中取最大值作为输入
    • 你是对的。即使解决方案更快,它也不适用于非常非常大的值。需要一种不同的方法。
    猜你喜欢
    • 1970-01-01
    • 2016-03-31
    • 2021-12-19
    • 2019-06-30
    • 1970-01-01
    • 2019-11-17
    • 2019-09-13
    • 2017-10-02
    • 2023-03-22
    相关资源
    最近更新 更多