1. 程式人生 > 其它 >【矩陣乘法】幼兒園的數學題Ⅰ

【矩陣乘法】幼兒園的數學題Ⅰ

技術標籤:其他矩陣乘法矩陣乘法

小目錄

連結

SSL 2513

題目描述


在這裡插入圖片描述
的前n項和

樣例輸入

1

樣例輸出

1

思路

打表找規律,發現f等價於斐波那契數列
那很顯然,題目求斐波那契前n項的和
n很大,所以考慮矩陣乘法
我們構建一個矩陣 a n s ans ans

f [ i − 1 ] f[i-1] f[i1] f [ i − 2 ] f[i-2] f[i2] s [ i − 2 ] s[i-2] s[i2]

考慮把這個矩陣向 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[i1]+f[i2],f[i1],s[i2]+f[i1])
考慮令它轉移的矩陣b

111
100
001

然後就是跑矩陣乘法就可以了

程式碼

#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]); }