簡體   English   中英

有什么方法可以減少時間復雜度,以找到該矩陣為n的冪?

[英]Is there any way to reduce time complexity to find this matrix to the power n?

我正在研究一個問題,我應該找到4x4矩陣的nth冪,其中n可以大到10^15並且由於答案中的值可能非常大,我可以使用modulo 10^9+7 給定矩陣為-

   2  1 -2 -1
A= 1  0  0  0
   0  1  0  0
   0  0  1  0 

我已經為此目的編寫了代碼,但是它的運行時間超過了預期的時間。 所以任何人都可以幫助我減少時間復雜度。

#define FOR(k,a,b) for(typeof(a) k=(a); k < (b); ++k)
typedef long long ll;
#define dim 4
struct matrix {
    long long a[dim][dim];
};
#define MOD 1000000007
matrix mul(matrix x, matrix y)
{
    matrix res;
    FOR(a, 0, dim) FOR(b, 0, dim) res.a[a][b] = 0;
    FOR(a, 0, dim) FOR(b, 0, dim) FOR(c, 0, dim) {
    ll temp = x.a[a][b] * y.a[b][c];
    if (temp <= -MOD || temp >= MOD)
        temp %= MOD;
    res.a[a][c] += temp;
    if (res.a[a][c] <= -MOD || res.a[a][c] >= MOD)
        res.a[a][c] %= MOD;
    }
    return res;
}

matrix power(matrix m, ll n)
{
    if (n == 1)
        return m;
    matrix u = mul(m, m);
    u = power(u, n / 2);
    if (n & 1)
        u = mul(u, m);
    return u;
}

matrix M, RP;
int main()
{
    FOR(a, 0, dim) FOR(b, 0, dim) M.a[a][b] = 0;
    M.a[0][0] = 2;
    M.a[0][1] = 1;
    M.a[0][2] = -2;
    M.a[0][3] = -1;
    M.a[1][0] = 1;
    M.a[2][1] = 1;
    M.a[3][2] = 1;
    int nt;
    scanf("%d", &nt);
    while (nt--) {
    ll n;
    scanf("%lld", &n);
    RP = power(M, n);
    FOR(a, 0, dim)
        FOR(b, 0, dim)
        printf("%lld\n", RP.a[a][b]);
    }
    return 0;
}

[評論員顯示此答案不完整。 答案保留在此處以供參考,但不再需要任何投票。 評論員是否會酌情添加更完整的答案?]

是。 准確地執行您想要的事情的絕佳方法是眾所周知的。 您必須對角化矩陣。

對角化將需要一些編程。 該理論在這里進行了說明。 14.6。 幸運的是,現有的矩陣代數庫(例如LAPACK)已經包含對角化例程。

@Haile正確有趣地觀察到,並非所有矩陣都是對角線化的,存在退化的情況。 我在這種情況下沒有太多實踐經驗。 有Schur分解(請參閱先前鏈接的資料的14.10節),但我通常看到Schur僅用於提出理論要點,而不是進行實際計算。 不過,我相信Schur會成功。 我懷疑,要實現它需要付出很多努力,但是即使在嚴格不可對角化矩陣的情況下,它也能奏效。

您可以利用多個測試用例來減少總計算量。

請注意,每次調用冪時,都會重新計算原始矩陣2的所有冪。 因此,對於10 ^ 15(約2 ^ 50)這樣的數字,您將最終對一個矩陣進行50次平方運算,並為該數字中的每個非零位計算一個乘法(可能是25次)。

如果您僅預先計算2的50次冪,則每個測試用例平均只需要25次乘法,而不是75次。

您可以將這個想法更進一步,並為您的求冪使用不同的基礎。 這將導致更多的預計算,但每個測試值的最終矩陣乘法更少。

例如,代替預先計算M ^ 2,M ^ 4,M ^ 8,M ^ 16,您可以預先計算[M ^ 1,M ^ 2,M ^ 3],[M ^ 4,M ^ 8,M ^ 12 ],[M ^ 16,M ^ 32,M ^ 48],因此M ^ 51將是(M ^ 3)*(M ^ 48)而不是M * M ^ 2 * M ^ 16 * M ^ 32

這並不是關於更快地對矩陣求冪的想法,而是關於加速整個程序的想法。

如果要求您執行10 ^ 4取冪,這並不意味着它們應該獨立進行。 您可以對請求進行排序,並為每個下一次計算重用先前的結果。

您還可以存儲先前計算的中間結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM