# 14071: 【原4071】Fibonacci数列

### 题目描述

author: Engineev 原OJ链接：https://acm.sjtu.edu.cn/OnlineJudge-old/problem/4071

5

8

## BugenZhao's solution

//
// Created by BugenZhao on 2019/5/17.
//

#include <iostream>
#include <string>

using std::ios, std::cin, std::cout, std::endl, std::string;
using ll=long long;
using ull=unsigned long long;

const int P = 1e9 + 7;

class Matrix2D {
public:
ll a, b, c, d;

Matrix2D(ll a, ll b, ll c, ll d) :
a(a), b(b), c(c), d(d) {}
};

Matrix2D operator*(const Matrix2D &x, const Matrix2D &y) {
ll a = x.a * y.a + x.b * y.c;
ll b = x.a * y.b + x.b * y.d;
ll c = x.c * y.a + x.d * y.c;
ll d = x.c * y.b + x.d * y.d;
return Matrix2D(a % P, b % P, c % P, d % P);
}

Matrix2D pow(const Matrix2D &m, ull p) {
if (p == 0) return Matrix2D(1, 0, 0, 1);
if (p == 1) return m;
Matrix2D tmp = pow(m, p / 2);
if (p % 2) return tmp * tmp * m;
else return tmp * tmp;
}

int main() {
ull n;
cin >> n;
Matrix2D ans = pow(Matrix2D(1, 1, 1, 0), n);
cout << ans.a << endl;
return 0;
}

## FineArtz's solution

/* Fibonacci数列 */
#include <iostream>
using namespace std;

const long long MOD = 1000000007;

class matrix{
public:
matrix(long long a, long long b, long long c, long long d)
: a11(a), a12(b), a21(c), a22(d) {}
matrix(const matrix &a) : a11(a.a11), a12(a.a12), a21(a.a21), a22(a.a22) {}
long long a11, a12, a21, a22;
};
inline matrix operator *(const matrix &m1, const matrix &m2){
matrix ret(0, 0, 0, 0);
ret.a11 = (m1.a11 * m2.a11 % MOD + m1.a12 * m2.a21 % MOD) % MOD;
ret.a12 = (m1.a11 * m2.a12 % MOD + m1.a12 * m2.a22 % MOD) % MOD;
ret.a21 = (m1.a21 * m2.a11 % MOD + m1.a22 * m2.a21 % MOD) % MOD;
ret.a22 = (m1.a21 * m2.a12 % MOD + m1.a22 * m2.a22 % MOD) % MOD;
return ret;
}
matrix pow(matrix x, long long n){
matrix ret(1, 0, 0, 1), t(x);
while (n != 0){
if (n & 1){
ret = ret * t;
}
t = t * t;
n >>= 1;
}
return ret;
}
int main(){
long long n;
cin >> n;
matrix f(1, 1, 1, 0);
f = pow(f, n + 1);
cout << f.a21 << endl;
}

## ligongzzz's solution

#include "iostream"
#include "cstdio"
#include "cstring"
#include "cmath"
using namespace std;

constexpr long long mod = (long long)(1e9 + 7);

class matrix {
public:
long long a11 = 0, a12 = 0;
long long a21 = 0, a22 = 0;

matrix() = default;
matrix(long long a11, long long a12, long long a21, long long a22) :a11(a11% mod), a12(a12% mod)
, a21(a21% mod), a22(a22% mod) {}

matrix(matrix&& other){
swap(*this, other);
}

void operator=(matrix&& other) {
swap(*this, other);
}

matrix&& operator*(const matrix& b) const{
matrix temp;
temp.a11 = (a11 * b.a11 + a12 * b.a21) % mod;
temp.a12 = (a11 * b.a12 + a12 * b.a22) % mod;
temp.a21 = (a21 * b.a11 + a22 * b.a21) % mod;
temp.a22 = (a21 * b.a12 + a22 * b.a22) % mod;
return std::move(temp);
}
};

matrix&& fast_pow(const matrix& a, long long b) {
matrix ans(1, 0, 0, 1), base(a.a11, a.a12, a.a21, a.a22);
for (; b; b >>= 1) {
if (b & 1LL)
ans = ans * base;
base = base * base;
}
return std::move(ans);
}

int main() {
long long n;
scanf("%lld", &n);

matrix temp(1, 1, 0, 0);
matrix to(1, 1, 1, 0);
matrix ans;
ans = temp * fast_pow(to, n - 1);
printf("%lld", ans.a11);

return 0;
}

## q4x3's solution

/**
* 矩阵快速幂求斐波那契
**/
#include <iostream>
#define ll long long

using namespace std;

const ll mo = 1e9 + 7;

struct mat {
ll a11, a12, a21, a22;
mat():a11(0), a12(1), a21(1), a22(1) {}
mat operator*(const mat &other) const {
mat tmp;
tmp.a11 = (a11 * other.a11 % mo + a12 * other.a21 % mo) % mo;
tmp.a12 = (a11 * other.a12 % mo + a12 * other.a22 % mo) % mo;
tmp.a21 = (a21 * other.a11 % mo + a22 * other.a21 % mo) % mo;
tmp.a22 = (a21 * other.a12 % mo + a22 * other.a22 % mo) % mo;
return tmp;
}
};

mat binary_pow(ll n) {
mat tmp, cache;
tmp.a11 = 1; tmp.a12 = 0; tmp.a21 = 0; tmp.a22 = 1;
while(n > 0) {
if(n & 1) {
tmp = tmp * cache;
}
cache = cache * cache;
n >>= 1;
}
return tmp;
}

ll n;

int main() {
cin >> n;
mat a = binary_pow(n);
printf("%lld\n", a.a22);
}

## skyzh's solution

#include <iostream>
using namespace std;

struct Matrix2x2 {
unsigned long long s[2][2];
};

const int S = 1e9 + 7;

Matrix2x2 mul(const Matrix2x2 &a, const Matrix2x2 &b) {
Matrix2x2 c;
/*
* a 0 1 b 0 1
* a 2 3 b 2 3
*/
c.s[0][0] = (a.s[0][0] * b.s[0][0] + a.s[0][1] * b.s[1][0]) % S;
c.s[0][1] = (a.s[0][0] * b.s[0][1] + a.s[0][1] * b.s[1][1]) % S;
c.s[1][0] = (a.s[1][0] * b.s[0][0] + a.s[1][1] * b.s[1][0]) % S;
c.s[1][1] = (a.s[1][0] * b.s[0][1] + a.s[1][1] * b.s[1][1]) % S;
return c;
}

unsigned long long fab(unsigned long long n) {
Matrix2x2 base, f;
base.s[0][0] = 1;
base.s[0][1] = 1;
base.s[1][0] = 0;
base.s[1][1] = 0;
f.s[0][0] = 1;
f.s[0][1] = 1;
f.s[1][0] = 1;
f.s[1][1] = 0;
while (n > 0) {
if (n & 1) base = mul(base, f);
f = mul(f, f);
n >>= 1;
}
return base.s[0][1];
}
int main() {
unsigned long long N;
cin >> N;
cout << fab(N) << endl;
return 0;
}

## victrid's solution

#include <cstdio>
#include <iostream>
#define mod 1000000007LL
using namespace std;
struct matrix {
long long a1, a2, b1, b2;
matrix operator*(const matrix& rhs) {
return matrix{(a1 * rhs.a1 + a2 * rhs.b1) % mod, (a1 * rhs.a2 + a2 * rhs.b2) % mod, (b1 * rhs.a1 + b2 * rhs.b1) % mod, (b1 * rhs.a2 + b2 * rhs.b2) % mod};
}
};
matrix fibo{1, 1, 1, 0};
matrix init{1, 0, 0, 1};
int main() {
long long n;
scanf("%lld", &n);
for (long long i = n - 1; i; i >>= 1) {
if (i & 1LL)
init = fibo * init;
fibo = fibo * fibo;
}
printf("%lld", (init.a1 + init.a2) % mod);
return 0;
}