![](/img/trans.png)
[英]Is there any way to merge two (or multiple) for loops to reduce the overall time complexity?
[英]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.