Skip to content

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;
}
Clone this wiki locally