#include <bits/stdc++.h>
std::ifstream INPUT_FILE("kfib.in");
std::ofstream OUTPUT_FILE("kfib.out");
class Matrice {
public:
Matrice( long n, long m);
virtual ~Matrice();
//get & set
bool isPatratica() const;
void setPatratica(bool patratica);
long int getM() const;
long int getN() const;
double getElement(long i,long j) const;
void setElement(long i,long j,double x);
//operatii
Matrice&operator+=(Matrice&);
Matrice&operator-=(Matrice&);
Matrice&operator+(Matrice&);
Matrice&operator-(Matrice&);
Matrice&operator*=(Matrice&);
Matrice&operator*(Matrice&);
Matrice&operator*=(double);
Matrice&operator*(double);
Matrice&operator/=(double);
Matrice&operator/(double);
Matrice operator^(long);
Matrice&operator=(Matrice);
bool operator==(Matrice&);
friend std::ostream& operator<<(std::ostream& os, const Matrice& mat);
// friend ostream& operator>>(ostream& os, const Matrice& mat);
//functii
static double Tr(Matrice mat);
static Matrice transpusa(Matrice mat);
static bool simetrica(Matrice mat);
static double determinant(Matrice mat);
static Matrice I(long marime);
protected:
private:
bool patratica;
long long m, n;
double **matrice;
double det(Matrice mat,long i,long j);
Matrice cofactor(Matrice mat,long i,long j);
void faMatricea();
Matrice puteri( Matrice&,long);
};
Matrice::Matrice( long n, long m){
//ctor
this->m=m;
this->n=n;
if(n==m) patratica= 1;
else patratica=0;
faMatricea();
}
Matrice::~Matrice(){
//dtor
}
double Matrice::Tr(Matrice mat) {
if(mat.isPatratica()){
double sum=0;
for(int tmp=0;tmp<mat.getM();tmp++) sum+=mat.getElement(tmp,tmp);
return sum;
}else{
std::cerr<<"Matricea nu e patratica!\n";
}
}
void Matrice::faMatricea() {
matrice=new double*[m];
for(long tmp=0;tmp<n;tmp++){
matrice[tmp]=new double[n];
}
}
bool Matrice::isPatratica() const {
return patratica;
}
void Matrice::setPatratica(bool patratica) {
Matrice::patratica = patratica;
}
long int Matrice::getM() const {
return m;
}
long int Matrice::getN() const {
return n;
}
Matrice &Matrice::operator+=(Matrice &mat) {
if(this->m==mat.getM() && this->n==mat.getN()){
for(long i=0;i<n;i++){
for(long j=0;j<m;j++) matrice[i][j]+=mat.getElement(i,j);
}
return *this;
}else{
std::cerr<<"Nu sunt de acelasi tip\n";
}
}
Matrice &Matrice::operator-=(Matrice &mat) {
if(this->m==mat.getM() && this->n==mat.getN()){
for(long i=0;i<n;i++){
for(long j=0;j<m;j++) matrice[i][j]-=mat.getElement(i,j);
}
return *this;
}else{
std::cerr<<"Nu sunt de acelasi tip\n";
}
}
Matrice &Matrice::operator+(Matrice &mat) {
if(this->m==mat.getM() && this->n==mat.getN()){
for(long i=0;i<n;i++){
for(long j=0;j<m;j++) matrice[i][j]+=mat.getElement(i,j);
}
return *this;
}else{
std::cerr<<"Nu sunt de acelasi tip\n";
}
}
Matrice &Matrice::operator-(Matrice &mat) {
if(this->m==mat.getM() && this->n==mat.getN()){
for(long i=0;i<n;i++){
for(long j=0;j<m;j++) matrice[i][j]-=mat.getElement(i,j);
}
return *this;
}else{
std::cerr<<"Nu sunt de acelasi tip\n";
}
}
Matrice &Matrice::operator*=(Matrice &mat) {
if(m==mat.getN()){
Matrice tmp(n,mat.getM());
for(long i=0;i<tmp.getN();i++){
for(long j=0;j<tmp.getM();j++){
for(long k=0;k<m;k++) tmp.setElement(i,j,tmp.getElement(i,j)+(getElement(i,k)*mat.getElement(k,i)));
}
}
return tmp;
}else{
std::cerr<<"Inmultirea nu se poate face\n";
}
}
Matrice &Matrice::operator*(Matrice &mat) {
if(m==mat.getN()){
Matrice tmp(n,mat.getM());
for(long i=0;i<tmp.getN();i++){
for(long j=0;j<tmp.getM();j++){
for(long k=0;k<m;k++) tmp.setElement(i,j,tmp.getElement(i,j)+(getElement(i,k)*mat.getElement(k,j)));
}
// std::cout<<tmp;
}
return (*this=tmp);
}else{
std::cerr<<"Inmultirea nu se poate face\n"<<mat;
std::cout<<*this;
}
}
Matrice &Matrice::operator*=(double x) {
for(long i=0;i<n;i++){
for(long j=0;j<m;j++){
matrice[i][j]*= x;
}
}
return *this;
}
Matrice &Matrice::operator*(double x) {
for(long i=0;i<n;i++){
for(long j=0;j<m;j++){
matrice[i][j]*= x;
}
}
return *this;
}
Matrice &Matrice::operator/=(double x) {
for(long i=0;i<n;i++){
for(long j=0;j<m;j++){
matrice[i][j]/= x;
}
}
return *this;
}
Matrice &Matrice::operator/(double x) {
for(long i=0;i<n;i++){
for(long j=0;j<m;j++){
matrice[i][j]/= x;
}
}
return *this;
}
Matrice Matrice::operator^(long x) {
Matrice tmp(*this);
return puteri(tmp,x);
}
Matrice &Matrice::operator=(Matrice mat) {
if(n==mat.getN() && m==mat.getM()){
for(long i=0;i<n;i++){
for(long j=0;j<m;j++){
setElement(i,j,mat.getElement(i,j));
}
}
return *this;
} else{
std::cerr<<"Matricele nu sunt de acelasi tip\n";
}
}
Matrice Matrice::transpusa(Matrice mat) {
Matrice tmp(mat.getM(),mat.getN());
for(long i=0;i<mat.getN();i++){
for(long j=0;j<mat.getM();j++){
tmp.setElement(j,i,mat.getElement(i,j));
}
}
return mat;
}
bool Matrice::simetrica(Matrice mat) {
if(transpusa(mat) == mat) return 1;
return 0;
}
double Matrice::determinant(Matrice mat) {
if(mat.getN()!=mat.getM()){
std::cerr<<"Matricea nu e patratica\n";
return 0;
}
}
double Matrice::getElement(long i, long j) const {
return matrice[i][j];
}
void Matrice::setElement(long i,long j,double x) {
matrice[i][j]=x;
}
Matrice Matrice::I(long marime) {
Matrice tmp(marime,marime);
for(long i=0;i<marime;i++){
for(long j=0;j<marime;j++){
if(i==j) tmp.setElement(i,j,1);
else tmp.setElement(i,j,0);
}
}
return tmp;
}
Matrice Matrice::puteri(Matrice &mat, long putere) {
if(!putere) return I(mat.getN());
if(putere==1) return mat;
if(putere%2) return puteri(mat*mat,(putere-1)/2);
return puteri(mat*mat,(putere)/2);
}
bool Matrice::operator==(Matrice &mat) {
if(n!=mat.getN() || m!=mat.getM())return false;
for(long i=0;i<n;i++){
for(long j=0;j<m;j++){
if(getElement(i,j)==mat.getElement(i,j)) return 0;
}
}
return 0;
}
std::ostream &operator<<(std::ostream &os, const Matrice &mat) {
for(long i=0;i<mat.getN();i++){
for(long j=0;j<mat.getM();j++){
os<<mat.getElement(i,j)<<" ";
}
os<<"\n";
}
}
int main() {
Matrice Z(2,2);
Matrice M1(1,2);
long n;
Z.setElement(0,0,0);
Z.setElement(0,1,1);
Z.setElement(1,0,1);
Z.setElement(1,1,1);
M1.setElement(0,0,0);
M1.setElement(0,1,1);
INPUT_FILE>>n;
Matrice rez(1,2);
Matrice rez1(2,2);
rez1=Z^n;
std::cout<<rez1;
std::cout<<rez;
rez=M1*rez1;
OUTPUT_FILE<<rez.getElement(0,1);
return 0;
}