我需要的高效解决方案

时间:2014-09-04 06:54:56

标签: java performance algorithm dynamic-programming

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

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

f [n] = M ^ n

我已使用Exponentiation_by_squaring

实施

那么效率更高吗?

3 个答案:

答案 0 :(得分:2)

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

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

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

答案 1 :(得分:2)

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

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

3 1 0

在每一步中,你将它(mod 1000000006)与矩阵相乘:

1 1 0
0 0 5
3 2 0

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

答案 2 :(得分:1)

您不需要计算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;
    }
}

我只尝试使用小值,但似乎有效。