120 lines
3.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* The Fibonacci sequence is defined by the recurrence relation:
*
* F_n = F_n1 + F_n2, where F_1 = 1 and F_2 = 1.
* It turns out that F_541, which contains 113 digits, is the first Fibonacci number for which the last nine digits are 1-9 pandigital
* (contain all the digits 1 to 9, but not necessarily in order). And F_2749, which contains 575 digits, is the first Fibonacci number
* for which the first nine digits are 1-9 pandigital.
*
* Given that F_k is the first Fibonacci number for which the first nine digits AND the last nine digits are 1-9 pandigital, find k.*/
#define _POSIX_C_SOURCE 199309L
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <gmp.h>
#include "projecteuler.h"
void fib_calc(mpz_t fib, int n);
int main(int argc, char **argv)
{
unsigned int i = 2, j, fib1 = 1, fib2 = 1, fibn, fib_int, found = 0;
char *fib_str;
double elapsed;
struct timespec start, end;
mpz_t fib;
clock_gettime(CLOCK_MONOTONIC, &start);
mpz_init(fib);
while(!found)
{
/* Calculate the next Fibonacci number modulo 10^9 and check if the result is 1-9 pandigital.*/
fibn = (fib1 + fib2) % 1000000000;
fib1 = fib2;
fib2 = fibn;
i++;
/* If the last 9 digits of fib_n are pandigital, calculate the ith Fibonacci number using
* the matrix representation.*/
if(is_pandigital(fibn, 9))
{
fib_calc(fib, i);
fib_str = mpz_get_str(NULL, 10, fib);
fib_int = 0;
for(j = 0; j < 9; j++)
{
fib_int *= 10;
fib_int += fib_str[j] - '0';
}
if(is_pandigital(fib_int, 9))
{
found = 1;
}
free(fib_str);
}
}
mpz_clear(fib);
clock_gettime(CLOCK_MONOTONIC, &end);
elapsed = (end.tv_sec - start.tv_sec) + (double)(end.tv_nsec - start.tv_nsec) / 1000000000;
printf("Project Euler, Problem 104\n");
printf("Answer: %d\n", i);
printf("Elapsed time: %.9lf seconds\n", elapsed);
return 0;
}
void fib_calc(mpz_t fib, int n)
{
int i;
mpz_t tmp, tmp00, tmp01, tmp10, tmp11;
mpz_t fib_matrix_base[2][2], fib_matrix[2][2];
mpz_init_set_ui(fib_matrix_base[0][0], 1);
mpz_init_set_ui(fib_matrix_base[0][1], 1);
mpz_init_set_ui(fib_matrix_base[1][0], 1);
mpz_init_set_ui(fib_matrix_base[1][1], 0);
mpz_init_set_ui(fib_matrix[0][0], 1);
mpz_init_set_ui(fib_matrix[0][1], 1);
mpz_init_set_ui(fib_matrix[1][0], 1);
mpz_init_set_ui(fib_matrix[1][1], 0);
mpz_inits(tmp, tmp00, tmp01, tmp10, tmp11, NULL);
for(i = 0; i < n - 1; i++)
{
mpz_mul(tmp00, fib_matrix[0][0], fib_matrix_base[0][0]);
mpz_mul(tmp, fib_matrix[0][1], fib_matrix_base[1][0]);
mpz_add(tmp00, tmp00, tmp);
mpz_mul(tmp01, fib_matrix[0][0], fib_matrix_base[0][1]);
mpz_mul(tmp, fib_matrix[0][1], fib_matrix_base[1][1]);
mpz_add(tmp01, tmp01, tmp);
mpz_mul(tmp10, fib_matrix[1][0], fib_matrix_base[0][0]);
mpz_mul(tmp, fib_matrix[1][1], fib_matrix_base[1][0]);
mpz_add(tmp10, tmp10, tmp);
mpz_mul(tmp11, fib_matrix[1][0], fib_matrix_base[0][1]);
mpz_mul(tmp, fib_matrix[1][1], fib_matrix_base[1][1]);
mpz_add(tmp11, tmp11, tmp);
mpz_set(fib_matrix[0][0], tmp00);
mpz_set(fib_matrix[0][1], tmp01);
mpz_set(fib_matrix[1][0], tmp10);
mpz_set(fib_matrix[1][1], tmp11);
}
mpz_set(fib, fib_matrix[0][1]);
mpz_clears(tmp, tmp00, tmp01, tmp10, tmp11, fib_matrix_base[0][0],
fib_matrix_base[0][1], fib_matrix_base[1][0], fib_matrix_base[1][1],
fib_matrix[0][0], fib_matrix[1][0], fib_matrix[1][1], NULL);
}