洛谷P1939 模板 矩陣加速(數列)

2022-09-03 04:27:11 字數 3960 閱讀 1048

設f1

=f2=

f3=1

,fn=

fn−3

+fn−

1f1​

=f2​

=f3​

=1,f

n​=f

n−3​

+fn−

1​。求fnfn

​。這篇部落格並不是專門來介紹矩陣乘法加速遞推的。

但是既然是模板題就提一下吧。

也就是說,對於兩個矩陣aa和b

b,在滿足第乙個矩陣的列數=第二個矩陣的行數時,這兩個矩陣就可以相乘。那麼假設aa是m

×pm×

p的矩陣,bb是p

×np×

n的矩陣,那麼他們相乘得到的矩陣c

c就是乙個m×n

m×n的矩陣。

而且對於矩陣c

c的任意元素ij

ij​,都等於矩陣a第i行的所有數字分別乘上矩陣b第j列的所有數字之和。(其實就是上圖的公式)

矩陣乘法和遞推關係最密切的例子就是斐波那契數列了。↓矩陣

乘法求斐

波那契數

列矩陣乘

法求斐波

那契數列

現在看不懂沒關係,可以慢慢理解。

我們知道,斐波那契數列有這樣的定義:fi

=fi−

1+fi

−2fi

​=fi

−1​+

fi−2

​那麼如果我們有乙個2×2

2×2的矩陣,其中第一行分別是fi−

1fi−

1​和fi

−2fi

−2​。我們的目標是把第一行承上乙個矩陣變成fif

i​和fi

−1fi

−1​。那麼應該怎麼辦呢?

首先,矩陣a

a和矩陣c

c都含有fi−

1fi−

1​這一項。那麼就先從這裡下手。

我們知道,矩陣cc的f

i−1f

i−1​

在第11

行第22

列。那麼,根據公式,可以得到c1

,2=a

1,1×

b2,1

+a1,

2×b2

,2c1

,2​=

a1,1

​×b2

,1​+

a1,2

​×b2

,2​也就是說fi

−1=f

i−1×

b2,1

+fi−

2×b2

,2fi

−1​=

fi−1

​×b2

,1​+

fi−2

​×b2

,2​那麼很明顯,我們可以得到b2,

1=1,

b2,2

=0b2

,1​=

1,b2

,2​=

0。這樣可以保證進行矩陣乘法之後c1,

2c1,

2​是fi

那麼現在來看矩陣c

c中的fif

i​。我們要保證的是c1

,1=a

1,1×

b1,1

+a1,

2×b2

,1c1

,1​=

a1,1

​×b1

,1​+

a1,2

​×b2

,1​也就是說fi

=fi−

1×b1

,1+f

i−2×

b2,1

fi​=

fi−1

​×b1

,1​+

fi−2

​×b2

,1​我們知道,fi=

fi−1

+fi−

2fi​

=fi−

1​+f

i−2​

。所以可以得到b1,

那麼整個矩陣b

b都被我們求出來了。

得到了fif

i​和fi

−1fi

−1​後,我們再將它乘一次矩陣b

b,就可以得到fi+

1fi+

1​和fi

fi​,又可以得到fi+

2fi+

2​和fi

+1..

.fi+

1​..

.這樣就可以得到fnf

n​了。但是!

你以為就結束了?

這樣的時間複雜度是o(n

m2)o

(nm2

),其中n

n表示求斐波那契數列的第n

n項,m

m表示矩陣的長寬。還不如遞推。而且遞推可以得到11到n

n的所有斐波那契數,而矩陣乘法只能求第nn項。

其實還有個地方可以優化。

我們求fnf

n​的時候其實是將原矩陣a

a乘了n−1

n−1次矩陣b

b的。也就是說目標

矩陣=a

×bn−

1目標矩

陣=a×

bn−1

看到n−1n

−1次方想到了什麼?

可以用快速冪!

我們用快速冪的思想求出bn−

1bn−

1,然後再乘上乙個矩陣a

a即可。

怎麼用快速冪?

其實是乙個道理。只不過把矩陣a

a乘矩陣b

b換成矩陣b

b乘矩陣b

b就可以了。

那麼最終的時間複雜度為o(m

3log

n)o(

m3lo

gn)。還是很優秀的。**

**下面進入正題。

可以發現矩陣

然後就是套模板了。。。

#include

#include

#define mod 1000000007

#define ll long long

using

namespace std;

const ll b[4]

[4]=

,,,}

;int t,n;

ll f[4]

,a[4][

4];void

mul(ll f[4]

,ll a[4]

[4])

void

mulself

(ll a[4]

[4])

void

ask(

int x)

}int

main()

memcpy

(a,b,

sizeof

(b))

; f[1]

=f[2

]=f[3]

=1;ask

(n-3);

printf

("%lld\n"

,f[3])

;}return0;

}

洛谷P1939 模板 矩陣加速(數列)

a 1 a 2 a 3 1 a x a x 3 a x 1 x 3 求a數列的第n項對1000000007 10 9 7 取餘的值。輸入格式 第一行乙個整數t,表示詢問個數。以下t行,每行乙個正整數n。輸出格式 每行輸出乙個非負整數表示答案。輸入樣例 1 368 10 輸出樣例 1 4 919 對於...

洛谷P1939 模板 矩陣加速(數列)

a 1 a 2 a 3 1 a x a x 3 a x 1 x 3 求a數列的第n項對1000000007 10 9 7 取餘的值。第一行乙個整數t,表示詢問個數。以下t行,每行乙個正整數n。每行輸出乙個非負整數表示答案。36 81049 19對於30 的資料 n 100 對於60 的資料 n 2 ...

洛谷P1939 模板 矩陣加速(數列)

傳送門 a 1 a 2 a 3 1 a n a a quad n 3 有 t 組詢問。對每組詢問,給定 n 求 a n mod 1000000007 t leq 100,n leq 2 times 10 9 首先假定你會矩陣快速冪 不會的看 這裡 那麼,我們可以構造列向量 c begina a a ...