【矩陣乘法】幼兒園的數學題Ⅰ
阿新 • • 發佈:2020-12-29
小目錄
連結
題目描述
求
的前n項和
樣例輸入
1
樣例輸出
1
思路
打表找規律,發現f等價於斐波那契數列
那很顯然,題目求斐波那契前n項的和
n很大,所以考慮矩陣乘法
我們構建一個矩陣
a
n
s
ans
ans
f [ i − 1 ] f[i-1] f[i−1] | f [ i − 2 ] f[i-2] f[i−2] | s [ i − 2 ] s[i-2] s[i−2] |
---|
考慮把這個矩陣向
f
[
i
]
f[i]
f[i]轉移
顯然,
f
[
i
]
=
(
f
[
i
−
1
]
+
f
[
i
−
2
]
,
f
[
i
−
1
]
,
s
[
i
−
2
]
+
f
[
i
−
1
]
)
f[i] = (f[i - 1] + f[i - 2], f[i-1], s[i-2]+f[i-1])
f[i]=(f[i−1]+f[i−2],f[i−1],s[i−2]+f[i−1])
考慮令它轉移的矩陣b
1 | 1 | 1 |
---|---|---|
1 | 0 | 0 |
0 | 0 | 1 |
然後就是跑矩陣乘法就可以了
程式碼
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const ll mo = 1000000007;
struct matrix {
ll n, m, a[5][5];
}a, b, ans, c;
ll n;
matrix operator *(matrix a, matrix b) {
c.n = a.n;
c.m = b.m;
for (ll i = 1; i <= c.n; i++)
for (ll j = 1; j <= c.m; j++)
c.a[i][j] = 0;
for (ll k = 1; k <= a.m; k++)
for (ll i = 1; i <= c.n; i++)
for (ll j = 1; j <= c.m; j++)
c.a[i][j] = (c.a[i][j] + (a.a[i][k] * b.a[k][j]) % mo) % mo;
return c;
}
void init()
{
ans.n = 1, ans.m = 3;
ans.a[1][1] = 1;
ans.a[1][2] = 1;
ans.a[1][3] = 1;
b.n = b.m = 3;
b.a[1][1] = b.a[1][2] = b.a[1][3] = 1;
b.a[2][1] = b.a[3][3] = 1;
}
void ksm(int x)
{
a = b;
x--;
while(x)
{
if(x & 1) a = a * b;
b = b * b;
x /= 2;
}
}
int main()
{
scanf("%d", &n);
if(n == 1) {
printf("1");
return 0;
}
init();
ksm(n - 1);//因為n = 1的時候已經處理過了,所以要減1
ans = ans * a;
printf("%lld", ans.a[1][3]);
}