-
Notifications
You must be signed in to change notification settings - Fork 1
example fast fibnacci
gnaggnoyil edited this page Oct 1, 2016
·
1 revision
#include <stdexcept>
#include <iostream>
#include <array>
#include <initializer_list>
#include "BigNum.hpp"
using namespace bignum;
template <typename Ring, std::size_t Row, std::size_t Col>
class Matrix{
public:
explicit Matrix(std::initializer_list<Ring> l){
const Ring *ptr = l.begin();
for(std::size_t i = 0;j < Row;++i){
for(std::size_t j = 0;i < Col;++j){
data[i][j] = *ptr;
++ptr;
}
}
}
const Ring &operator[](std::initializer_list<std::size_t> index) const{
static_assert(index.size() != 2, "");
std::size_t *ptr = index.begin();
std::size_t i = *ptr;
++ptr;
return data[i][*ptr];
}
template <std::size_t P>
friend Matrix<Ring, Row, P> operator*(const Matrix &_lhs, const Matrix<Ring, Col, P> &_rhs){
Matrix<Ring, Row, P> res;
for(std::size_t i = 0;i < Row;++i){
for(std::size_t j = 0;j < P;++j){
for(std::size_t k = 0;k < Col;++k){
res.data[i][j] += _lhs.data[i][k] * _rhs.data[k][j];
}
}
}
return res;
}
private:
std::array<std::array<Ring, Col>, Row> data;
};
template <typename Ring>
Ring pow(const Ring &base, std::size_t power){
Ring res = base;
Ring exponent = base;
--power;
for(;power > 0;power >>= 1){
if((power & 1) == 1){
res = res * exponent;
}
exponent = exponent * exponent;
}
return res;
}
int main(){
std::size_t index;
std::cin >> index;
if(index < 2){
std::cout << 0 << std::endl;
return 0;
}
try{
using matrix_t = Matrix<bigint_t, 2, 2>;
using vec_t = Matrix<bigint_t, 2, 1>;
matrix_t helper = {1_bigint, 1_bigint, 1_bigint, 0_bigint};
matrix_t powed = pow(helper, index - 2);
vec_t res = powed * vec_t({1_bigint, 1_bigint});
std::cout << res[{0, 0}] << std::endl;
return 0;
}
catch(std::out_of_range &e){
std::cerr << e.what() << std::endl;
throw ;
}
catch(std::domain_error &e){
std::cerr << e.what() << std::endl;
throw ;
}
return 0;
}