📌  相关文章
📜  查找第N个项(矩阵求幂示例)

📅  最后修改于: 2021-05-04 14:20:13             🧑  作者: Mango

我们提供了一个递归函数,该递归函数以其他术语的形式描述了第N个术语。在本文中,我们以具体示例为例。
 $T_{n} = 2*T_{n-1}+3*T{n-2}$  Given, $T_0=1$  $T_1=1$
现在给定n,则必须使用上述公式找出第n个项。

例子:

Input : n = 2
Output : 5

Input : n = 3
Output :13

先决条件:

基本方法:只需迭代n个项即可解决此问题。每次您找到一个术语时,使用该术语都可以找到下一个,依此类推。但是这个问题的时间复杂度为O(n)。

优化方法
所有这些问题,其中的一个术语是线性方式的其他术语的函数。然后可以使用Matrix(请参阅:Matrix Exponentiation)解决这些问题。首先我们制作变换矩阵,然后仅使用矩阵求幂来找到第N个项。
分步方法包括:
步骤1.确定k依赖于T(i)的项数。
在我们的示例中,T(i)取决于两个项。因此,k = 2

步骤2.确定初始值
如本文所述,T0 = 1,T1 = 1。

步骤3.确定TM,即转换矩阵。
这是解决递归关系的最重要步骤。在这一步中,我们必须制作尺寸为k * k的矩阵。
这样的
T(i)= TM *(初始值向量)
此处的初始值向量是包含初始值的向量。我们将此向量命名为initial
 $ So, Initial Vector=\left[ \begin{array}{c} T_1 & T_0\\ \end{array} \right] $  Now find Transformation matrix. $TM=\left[ \begin{array}{cc} 2 & 3\\ 1 & 0 \\ \end{array} \right]$  Now, First row of T2 give us 2nd term. $T_2=\left[ \begin{array}{cc} 2 & 3\\ 1 & 0 \\ \end{array} \right]*\left[ \begin{array}{c} T_1 & T_0\\ \end{array} \right]$   So, general term will be, First row of Tn. $T_n=\left[ \begin{array}{cc} 2 & 3\\ 1 & 0 \\ \end{array} \right]^{n-1}*\left[ \begin{array}{c} T_1 & T_0\\ \end{array} \right]$  So, finally we have Tn=$TM^{n-1}*Intial Vector$  And this power of matrix can be calculated using matrix exponenciation in O(logn).

下面是实现上述方法的程序

C++
// CPP program to find n-th term of a recursive
// function using matrix exponentiation.
#include 
using namespace std;
#define MOD 1000000009
  
#define ll long long int
  
ll power(ll n)
{
    if (n <= 1)
        return 1;
  
    // This power function returns first row of
    // {Transformation Matrix}^n-1*Initial Vector
    n--;
  
    // This is an identity matrix.
    ll res[2][2] = { 1, 0, 0, 1 };
  
    // this is Transformation matrix.
    ll tMat[2][2] = { 2, 3, 1, 0 };
  
    // Matrix exponentiation to calculate power of {tMat}^n-1
    // store res in "res" matrix.
    while (n) {
  
        if (n & 1) {
            ll tmp[2][2];
            tmp[0][0] = (res[0][0] * tMat[0][0] + res[0][1] * tMat[1][0]) % MOD;
            tmp[0][1] = (res[0][0] * tMat[0][1] + res[0][1] * tMat[1][1]) % MOD;
            tmp[1][0] = (res[1][0] * tMat[0][0] + res[1][1] * tMat[1][0]) % MOD;
            tmp[1][1] = (res[1][0] * tMat[0][1] + res[1][1] * tMat[1][1]) % MOD;
            res[0][0] = tmp[0][0];
            res[0][1] = tmp[0][1];
            res[1][0] = tmp[1][0];
            res[1][1] = tmp[1][1];
        }
        n = n / 2;
        ll tmp[2][2];
        tmp[0][0] = (tMat[0][0] * tMat[0][0] + tMat[0][1] * tMat[1][0]) % MOD;
        tmp[0][1] = (tMat[0][0] * tMat[0][1] + tMat[0][1] * tMat[1][1]) % MOD;
        tmp[1][0] = (tMat[1][0] * tMat[0][0] + tMat[1][1] * tMat[1][0]) % MOD;
        tmp[1][1] = (tMat[1][0] * tMat[0][1] + tMat[1][1] * tMat[1][1]) % MOD;
        tMat[0][0] = tmp[0][0];
        tMat[0][1] = tmp[0][1];
        tMat[1][0] = tmp[1][0];
        tMat[1][1] = tmp[1][1];
    }
  
    // res store {Transformation matrix}^n-1
    // hence will be first row of res*Initial Vector.
    return (res[0][0] * 1 + res[0][1] * 1) % MOD;
}
  
// Driver code
int main()
{
    ll n = 3;
    cout << power(n);
    return 0;
}


Java
// Java program to find n-th term of a recursive
// function using matrix exponentiation.
class GfG {
  
    static int MAX = 100;
    static int MOD = 1000000009;
    static int power(int n)
    {
        if (n <= 1) {
            return 1;
        }
  
        // This power function returns first row of
        // {Transformation Matrix}^n-1*Initial Vector
        n--;
  
        // This is an identity matrix.
        int res[][] = { { 1, 0 }, { 0, 1 } };
  
        // this is Transformation matrix.
        int tMat[][] = { { 2, 3 }, { 1, 0 } };
  
        // Matrix exponentiation to calculate power of {tMat}^n-1
        // store res in "res" matrix.
        while (n > 0) {
  
            if (n % 2 == 1) {
                int tmp[][] = new int[2][2];
                tmp[0][0] = (res[0][0] * tMat[0][0]
                             + res[0][1] * tMat[1][0])
                            % MOD;
                tmp[0][1] = (res[0][0] * tMat[0][1]
                             + res[0][1] * tMat[1][1])
                            % MOD;
                tmp[1][0] = (res[1][0] * tMat[0][0]
                             + res[1][1] * tMat[1][0])
                            % MOD;
                tmp[1][1] = (res[1][0] * tMat[0][1]
                             + res[1][1] * tMat[1][1])
                            % MOD;
                res[0][0] = tmp[0][0];
                res[0][1] = tmp[0][1];
                res[1][0] = tmp[1][0];
                res[1][1] = tmp[1][1];
            }
  
            n = n / 2;
            int tmp[][] = new int[2][2];
            tmp[0][0] = (tMat[0][0] * tMat[0][0]
                         + tMat[0][1] * tMat[1][0])
                        % MOD;
            tmp[0][1] = (tMat[0][0] * tMat[0][1]
                         + tMat[0][1] * tMat[1][1])
                        % MOD;
            tmp[1][0] = (tMat[1][0] * tMat[0][0]
                         + tMat[1][1] * tMat[1][0])
                        % MOD;
            tmp[1][1] = (tMat[1][0] * tMat[0][1]
                         + tMat[1][1] * tMat[1][1])
                        % MOD;
            tMat[0][0] = tmp[0][0];
            tMat[0][1] = tmp[0][1];
            tMat[1][0] = tmp[1][0];
            tMat[1][1] = tmp[1][1];
        }
  
        // res store {Transformation matrix}^n-1
        // hence wiint be first row of res*Initial Vector.
        return (res[0][0] * 1 + res[0][1] * 1) % MOD;
    }
  
    // Driver code
    public static void main(String[] args)
    {
        int n = 3;
        System.out.println(power(n));
    }
}
  
// This code contributed by Rajput-Ji


Python3
# Python3 program to find n-th term of a recursive
# function using matrix exponentiation.
MOD = 1000000009;
  
def power(n):
    if (n <= 1):
        return 1;
  
    # This power function returns first row of
    # {Transformation Matrix}^n-1 * Initial Vector
    n-= 1;
  
    # This is an identity matrix.
    res = [[1, 0], [0, 1]];
  
    # this is Transformation matrix.
    tMat = [[2, 3], [1, 0]];
  
    # Matrix exponentiation to calculate 
    # power of {tMat}^n-1 store res in "res" matrix.
    while (n):
        if (n & 1):
            tmp = [[0 for x in range(2)] for y in range(2)];
            tmp[0][0] = (res[0][0] * tMat[0][0] + 
                        res[0][1] * tMat[1][0]) % MOD;
            tmp[0][1] = (res[0][0] * tMat[0][1] + 
                        res[0][1] * tMat[1][1]) % MOD;
            tmp[1][0] = (res[1][0] * tMat[0][0] + 
                        res[1][1] * tMat[1][0]) % MOD;
            tmp[1][1] = (res[1][0] * tMat[0][1] +
                        res[1][1] * tMat[1][1]) % MOD;
            res[0][0] = tmp[0][0];
            res[0][1] = tmp[0][1];
            res[1][0] = tmp[1][0];
            res[1][1] = tmp[1][1];
      
        n = n // 2;
        tmp = [[0 for x in range(2)] for y in range(2)];
        tmp[0][0] = (tMat[0][0] * tMat[0][0] + 
                    tMat[0][1] * tMat[1][0]) % MOD;
        tmp[0][1] = (tMat[0][0] * tMat[0][1] + 
                    tMat[0][1] * tMat[1][1]) % MOD;
        tmp[1][0] = (tMat[1][0] * tMat[0][0] + 
                    tMat[1][1] * tMat[1][0]) % MOD;
        tmp[1][1] = (tMat[1][0] * tMat[0][1] + 
                    tMat[1][1] * tMat[1][1]) % MOD;
        tMat[0][0] = tmp[0][0];
        tMat[0][1] = tmp[0][1];
        tMat[1][0] = tmp[1][0];
        tMat[1][1] = tmp[1][1];
  
    # res store {Transformation matrix}^n-1
    # hence will be first row of res * Initial Vector.
    return (res[0][0] * 1 + res[0][1] * 1) % MOD;
  
# Driver code
n = 3;
print(power(n));
      
# This code is contributed by mits


C#
// C# program to find n-th term of a recursive
// function using matrix exponentiation.
using System;
  
class GfG {
  
    // static int MAX = 100;
    static int MOD = 1000000009;
    static int power(int n)
    {
        if (n <= 1) {
            return 1;
        }
  
        // This power function returns first row of
        // {Transformation Matrix}^n-1*Initial Vector
        n--;
  
        // This is an identity matrix.
        int[, ] res = { { 1, 0 }, { 0, 1 } };
  
        // this is Transformation matrix.
        int[, ] tMat = { { 2, 3 }, { 1, 0 } };
  
        // Matrix exponentiation to calculate power of {tMat}^n-1
        // store res in "res" matrix.
        while (n > 0) {
  
            if (n % 2 == 1) {
                int[, ] tmp = new int[2, 2];
                tmp[0, 0] = (res[0, 0] * tMat[0, 0]
                             + res[0, 1] * tMat[1, 0])
                            % MOD;
                tmp[0, 1] = (res[0, 0] * tMat[0, 1]
                             + res[0, 1] * tMat[1, 1])
                            % MOD;
                tmp[1, 0] = (res[1, 0] * tMat[0, 0]
                             + res[1, 1] * tMat[1, 0])
                            % MOD;
                tmp[1, 1] = (res[1, 0] * tMat[0, 1]
                             + res[1, 1] * tMat[1, 1])
                            % MOD;
                res[0, 0] = tmp[0, 0];
                res[0, 1] = tmp[0, 1];
                res[1, 0] = tmp[1, 0];
                res[1, 1] = tmp[1, 1];
            }
  
            n = n / 2;
            int[, ] tmp1 = new int[2, 2];
            tmp1[0, 0] = (tMat[0, 0] * tMat[0, 0]
                          + tMat[0, 1] * tMat[1, 0])
                         % MOD;
            tmp1[0, 1] = (tMat[0, 0] * tMat[0, 1]
                          + tMat[0, 1] * tMat[1, 1])
                         % MOD;
            tmp1[1, 0] = (tMat[1, 0] * tMat[0, 0]
                          + tMat[1, 1] * tMat[1, 0])
                         % MOD;
            tmp1[1, 1] = (tMat[1, 0] * tMat[0, 1]
                          + tMat[1, 1] * tMat[1, 1])
                         % MOD;
            tMat[0, 0] = tmp1[0, 0];
            tMat[0, 1] = tmp1[0, 1];
            tMat[1, 0] = tmp1[1, 0];
            tMat[1, 1] = tmp1[1, 1];
        }
  
        // res store {Transformation matrix}^n-1
        // hence wiint be first row of res*Initial Vector.
        return (res[0, 0] * 1 + res[0, 1] * 1) % MOD;
    }
  
    // Driver code
    public static void Main()
    {
        int n = 3;
        Console.WriteLine(power(n));
    }
}
  
// This code contributed by mits


PHP


输出:
13

时间复杂度: O(Log n)

使用相同的想法在O(Log n)中找到第n个斐波那契数