Cod sursa(job #1518647)

Utilizator glbglGeorgiana bgl glbgl Data 6 noiembrie 2015 01:20:39
Problema Al k-lea termen Fibonacci Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 1.6 kb
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fstream>

#define DIVISOR 666013

using namespace std;

ifstream in("kfib.in");
ofstream out("kfib.out");


void MMultiply(long long A[2][2], long long B[2][2], long long rez[2][2]){


	for(int i = 0; i < 2; ++i)
		for(int j = 0; j < 2; ++j)
			rez[i][j] = 0;

	for(int i = 0; i < 2; ++i)
		for(int j = 0; j < 2; ++j)
			for(int k = 0; k < 2; ++k)
				rez[i][j] = (rez[i][j] + A[i][k]*B[k][j]) % DIVISOR;
}

void VMultiply(long long v[2], long long M[2][2], long long rez[2]){

	rez[0] = 0;
	rez[1] = 0;

	for(int i = 0; i < 2; ++i)
			for(int k = 0; k < 2; ++k)
				rez[i] = (rez[i] + v[k] * M[k][i]) % DIVISOR;
}


void copy2D(long long M[2][2], long long r[2][2]){

	for(int i = 0; i < 2; ++i)
		for(int j = 0; j < 2; ++j)
			r[i][j] = M[i][j];
}

void MtrxLgPow(long long Z[2][2], long long P, long long rez[2][2]){

	for(int i = 0; i < 2; ++i)
		for(int j = 0; j < 2; ++j)
			rez[i][j] = 0;

	int ok = 0;
	long long Y[2][2] = {{1,1},{1,1}};

	long long tmp[2][2];

	while( P > 1){
		if(P % 2 == 0){
			MMultiply(Z,Z,tmp);		
			copy2D(tmp,Z);
			P /= 2; 
		}
		else{
			ok = 1;
			MMultiply(Z,Z,tmp);
			copy2D(tmp,Z);
			P -= 1;
		}
	}

	if(ok == 1) MMultiply(Z,Y,rez);
	else copy2D(Z,rez);
	// for(int i = 0; i < 2; ++i)
	// 			for(int j = 0; j < 2; ++j)
	// 				printf("%lld\n", rez[i][j]);
}


long long KFib(int k){

	long long fib[2] = {0,1};
	long long Z[2][2] = {{0,1},{1,1}};
	long long rez[2];
	long long r[2][2];

	MtrxLgPow(Z,k-1, r);

	VMultiply(fib, r, rez);

	return rez[1];
}


int main(){


	int k;
	in >> k;

	out << KFib(k) << "\n";
	return 0;
}