矩阵快速幂-Fibonacci

有 志 者 事 竟 成,破 釜 沉 舟,百 二 秦 关 终 属 楚;
苦 心 人 天 不 负,卧 薪 尝 胆,三 千 越 甲 可 吞 吴!

博客有着知识错误,待改正之后,又是一篇好博客! 2020.6.30🤞

矩阵快速幂-Fibonacci

LDU暑假第一次学习记

今天学习了一波矩阵快速幂,受益良多!!!
矩阵快速幂的目的就斐波那契这个例子来说,是把一个递推式,换成可以类似于一个数一样,来进行快速幂运算。已达到在log(n)的复杂度内实现求第n项。
首先亮出我的矩阵快速幂模板

struct Mat {
	ll m[10][10];
};
Mat Mat_mul(Mat x, Mat y, ll mat_size, ll mod) {
	Mat temp;
	memset(temp.m, 0, sizeof(temp));
	for (int i = 0; i < mat_size; i++)for (int j = 0; j < mat_size; j++)for (int k = 0; k < mat_size; k++)
		temp.m[i][j] = (temp.m[i][j] % mod + x.m[i][k] * y.m[k][j]) % mod;
	return temp;
}
Mat Create_identity_matrix(ll mat_size) {
	Mat temp;
	memset(temp.m, 0, sizeof(temp.m));
	for (int i = 0; i < mat_size; i++)temp.m[i][i] = 1;
	return temp;
}
Mat mat_qpow(Mat* mat, ll power, ll mat_size, ll mod) {
	Mat res = Create_identity_matrix(mat_size);
	while (power) {
		if (power & 1) res = Mat_mul(res, *mat, mat_size, mod);
		*mat = Mat_mul(*mat, *mat, mat_size, mod), power >>= 1;
	}
	return res;
}

用法也很简单

int main()
{
	Mat temp;
	memset(temp.m, 0, sizeof(temp.m));
	temp.m[0][0] = temp.m[0][1] = temp.m[1][0] = 1;
	cout << mat_qpow(&temp, read, 2, 10000).m[1][0] << endl;
}

知道怎么用了之后,咱们就开始解决如何使用应用矩阵快速幂。

应用

通常咱们用得到的几个关系式是Fn,Sn,Pn,分别是,第n项,前n项和,前n项和的前n项和。😄
咱们用结果推前面的方法来求解A
我们可以先列出一个关系
A×(Fn1Fn2)=(FnFn1) A \times \binom{F_{n-1}}{F_{n-2}}=\binom{F_{n}}{F_{n-1}}
这个A矩阵就是中间的桥梁来记录着每一个Fn项和Fn-1项
这里加上一个关系式
Fn=Fn1+Fn2F_{n}=F_{n-1}+F_{n-2}
我们很容易可以理解出A的shape一定是(2,2)那么,怎么怎么去推导A呢
首先看Fn,他可以由Fn-1和Fn-2组合而成,所以第一次推到后矩阵的到
(11??) \begin{pmatrix} 1 & 1 \\ ? & ? \end{pmatrix}
然后发现Fn-1直接和Fn-1对应
那么结果是
A=(1110) A=\begin{pmatrix} 1 & 1 \\ 1 & 0 \end{pmatrix}
然后这个A运算多少次就对应了Fn
注意这里填的数不是True or False,是对应的初始值
如果开头是规定F0=0下1 2 3 5 8这样的数列,那么我们应该填的是
A=(2110) A=\begin{pmatrix} 2 & 1 \\ 1 & 0 \end{pmatrix}

Fibonacci

题目描述

我们知道斐波那契数列, F0=0, F1=1, Fn=Fn−1+Fn−2,求Fn mod 10000 。

输入

多组数据,每组数据一行,一个整数 n。
输入以 -1 结束。

输出

对于每组数据,输出 Fn mod 10000。

Sample Input

0
9
999999999
1000000000
-1

Sample Output

0
34
626
6875

Hint

n ≤ 109

题目分析
矩阵快速幂的基本应用

AC时间到

#include <unordered_map>
#include<algorithm>
#include<iostream>
#include<string.h>
#include <iomanip>
#include<stdio.h>
#include<utility>
#include<vector>
#include<string>
#include<math.h>
#include<cmath>
#include<queue>
#include<stack>
#include<deque>
#include<map>
#include<set>
#pragma warning(disable:4244)
#define PI 3.141592653589793
#pragma GCC optimize(2)
#define accelerate cin.tie(NULL);cout.tie(NULL);ios::sync_with_stdio(false);
#define EPS 1.0e-8
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll ll_inf = 9223372036854775807;
const int int_inf = 2147483647;
const short short_inf = 32767;
const char char_inf = 127;
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll read() {
	ll c = getchar(), Nig = 1, x = 0;
	while (!isdigit(c) && c != '-')c = getchar();
	if (c == '-')Nig = -1, c = getchar();
	while (isdigit(c))x = ((x << 1) + (x << 3)) + (c ^ '0'), c = getchar();
	return Nig * x;
}
inline void out(ll a) {
	if (a < 0)putchar('-'), a = -a;
	if (a >= 10)out(a / 10);
	putchar(a % 10 + '0');
}
ll phi(ll n)
{
	ll ans = n, mark = n;
	for (ll i = 2; i * i <= mark; i++)
		if (n % i == 0) { ans = ans * (i - 1) / i; while (n % i == 0)n /= i; }
	if (n > 1)ans = ans * (n - 1) / n; return ans;
}
ll qpow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1)res = (res * x) % mod;
		x = (x * x) % mod;
		n >>= 1;
	}
	return res;
}
struct Mat {
	ll m[10][10];
};
Mat Mat_mul(Mat x, Mat y, ll mat_size, ll mod) {
	Mat temp;
	memset(temp.m, 0, sizeof(temp));
	for (int i = 0; i < mat_size; i++)for (int j = 0; j < mat_size; j++)for (int k = 0; k < mat_size; k++)
		temp.m[i][j] = (temp.m[i][j] % mod + x.m[i][k] * y.m[k][j]) % mod;
	return temp;
}
Mat Create_identity_matrix(ll mat_size) {
	Mat temp;
	memset(temp.m, 0, sizeof(temp.m));
	for (int i = 0; i < mat_size; i++)temp.m[i][i] = 1;
	return temp;
}
Mat mat_qpow(Mat* mat, ll power, ll mat_size, ll mod) {
	Mat res = Create_identity_matrix(mat_size);
	while (power) {
		if (power & 1) res = Mat_mul(res, *mat, mat_size, mod);
		*mat = Mat_mul(*mat, *mat, mat_size, mod), power >>= 1;
	}
	return res;
}
#define Floyd for(int k = 1; k <= n; k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
#define read read()
int main()
{
	Mat temp, res;
	while (1)
	{
		ll n = read;
		if (n == -1)break;
		memset(temp.m, 0, sizeof(temp.m));
		temp.m[0][0] = temp.m[0][1] = temp.m[1][0] = 1;
		out(mat_qpow(&temp, n, 2, 10000).m[1][0]);
		puts("");
	}
}

By-轮月

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章