Solving Recurrences

Solving Recurrences
A recurrence is an equation in the form F(X) = a1*F(X-1) + a2*F(X-2)... ak*F(X-k)

The idea is to find F(X) for large X in O(log(N)*k^2) time.

Let the matrix A be the following:

[ a1 a2 a3 ... ak]

[ 1 0 0 ...... 0]

[ 0 1 0 ....... 0]

...

[0 0 0 ...... 1 0]

Assuming F(0) = 0, then A^X * F(1) gives F(X) public static double[][] mpow(double[][] a, long pow) {        if (pow == 0) {            double[][] v = new double[a.length][a.length] ; for (int i = 0 ; i < v.length ; i ++) for (int j = 0 ; j < v.length ; j ++) {                    if (i == j) v[i][j] = 1 ; else v[i][j] = 0 ; }            return v ; }        if (pow == 1) return a ; if (pow % 2 == 0) {            double[][] t = mpow(a,pow/2) ; return m(t,t) ; }        return m(a,mpow(a,pow-1)) ; }    public static double[][] m(double[][] a, double[][] b)     { double[][] c = new double[a.length][a.length] ; for (int i = 0 ; i < a.length ; i ++) for (int j = 0 ; j < a.length ; j ++) {                c[i][j] = 0 ; for (int k = 0 ; k < a.length ; k ++) {                    c[i][j] += a[i][k] * b[k][j] ; }            }         return c ; } Implementation may require BigInteger, long, or modulus.

Special Case:

If a1 = a2 = a3 ... = ak,

There is a DP solution in O(N). Note that the solution is NOT O(N*k); k may be VERY large and it still does not affect the run-time (e.g. if K is 1000 terms, then an O(N*K) solution may be too slow). This will work for N ~ 1,000,000; more than that and you can't do that much DP.

Idea:

F(X) = aF(X-1)+aF(X-2)...aF(X-K)

F(X-1) = aF(X-2)+aF(X-3)...aF(X-K-1)

F(X)-F(X-1)=aF(X-1)-aF(X-K-1)

F(X) = F(X-1)*(1+a)-aF(X-K-1)

Just do linear DP on this recurrence (if X-K-1 is < 0, ignore the second term).

If the recurrence is from F(X-J) to F(X-K), there is still an O(N) solution:

F(X) = aF(X-J)+aF(X-J-1)...aF(X-K) F(X-1) = aF(X-J-1)+aF(X-J-2)...aF(X-K-1) F(X) = F(X-1) + aF(X-J) - aF(X-K-1)