2421. Fibonacci numbers
As is known, the Fibonacci
sequence is defined as:
F(0) =
0, F(1) = 1, F(n) = F(n – 1) + F(n – 2) (äëÿ âñåõ n >
1).
It was named after the
Italian mathematician Leonardo Fibonacci, also known as Leonardo of Pisa.
Given the values of n and m, find the greatest common divisor of F(n) and F(m).
Input. Each line is a separate test
case that contains two integers n and
m (1 ≤ n, m
≤ 1018). The number of test cases does not exceed 1000.
Output. For each test case print in
a separate line the value of GCD(F(n),
F(m)), taken by modulo 108.
Sample input |
Sample output |
2 3 1 1 100 200 |
1 1 61915075 |
Fibonacci numbers
It is known that GCD(F(n), F(m)) = F(GCD(n,m)). That is, in the problem you should
find the k-th Fibonacci number, taken
modulo 108, where k = GCD(n,m).
Since n, m ≤ 1018, then k ≤ 1018. Therefore, it is necessary to compute the value of F(k)
mod 108 in time O(log2k).
Theorem. .
Base if induction. For k = 1: , which is true since
F0 = 0, F1 = 1,
F2 = 1
Induction step.
It remains to
implement the exponentiation
of the matrix to the power of k in time
O(log2k).
Declare the class Matrix and the constructor.
class
Matrix
{
public:
long long a, b, c, d;
Matrix(long long a = 1, long long b = 0,
long long c = 0, long long d = 1)
{
this->a
= a; this->b = b;
this->c
= c; this->d = d;
}
Overload the matrix multiplication
operator. All computations are carried out
MOD = 108.
Matrix operator*
(const Matrix &x)
{
Matrix res;
res.a = (a * x.a + b * x.c) % MOD;
res.b = (a * x.b + b * x.d) % MOD;
res.c = (c * x.a + d * x.c) % MOD;
res.d = (c * x.b + d * x.d) % MOD;
return res;
}
Overload the operator of exponentiation a matrix to the power n.
The time complexity of the algorithm is O(log2n).
Matrix operator^
(long long n)
{
Matrix x(*this);
if (n == 0)
return Matrix();
if (n & 1) return
x * (x ^ (n - 1));
return (x *
x) ^ (n/2);
}
};
Function fib(n) returns the n-th Fibonacci number F(n)
modulo 108.
long long fib(long long n)
{
Matrix res(1,1,1,0);
res = res ^ n;
return res.b;
}
The main part of
the program. Read the
input data, compute and print the value of F(GCD(n, m)). The function
gcd computes the greatest common divisor of two
numbers.
while(scanf("%lld %lld",&n,&m) == 2)
{
d = gcd(n,m);
printf("%lld\n",fib(d));
}
It is known that Fn+m
= Fm Fn+1 + Fm-1
Fn.
·
if m = n, then F2n
= Fn Fn+1
+ Fn-1 Fn.
·
if m = n + 1, then F2n+1 = Fn+1
Fn+1 + Fn Fn.
Process the cases F0 =
0 and F1 =
F2 =1 separately. Time complexity is O(log2n).
#include <cstdio>
#include <map>
#define MOD 100000000
using namespace std;
map<long long, long long> F;
long long gcd(long long a, long long b)
{
return (!b) ? a : gcd(b,a % b);
}
long long fib(long long n)
{
if (n == 0) return 0;
if (n == 1) return 1;
if (n == 2) return 1;
if (F[n]) return
F[n];
long long k = n / 2;
if (n % 2 == 1) // n=2*k+1
return F[n] = (fib(k) * fib(k) + fib(k+1) * fib(k+1))
% MOD;
else // n=2*k
return F[n] = (fib(k) * fib(k+1) + fib(k-1) * fib(k))
% MOD;
}
long long a, b, d;
int main(void)
{
while(scanf("%lld
%lld",&a,&b) == 2)
{
d = gcd(a,b);
printf("%lld\n",fib(d));
}
return 0;
}
Java realization
import java.util.*;
public class Main
{
static
HashMap<Long, Long> F = new
HashMap<Long, Long>();
static long MOD = 100000000;
static long gcd(long a, long b)
{
return (b == 0) ? a : gcd(b,a % b);
}
static long fib(long n)
{
if (n == 0) return 0;
if (n == 1) return 1;
if (n == 2) return 1;
if (F.containsKey(n)) return F.get(n);
long k = n / 2;
if (n % 2 == 1)
{
F.put(n, (fib(k) * fib(k) + fib(k+1) * fib(k+1)) % MOD);
return F.get(n);
}
else
{
F.put(n, (fib(k) * fib(k+1) + fib(k-1) * fib(k)) % MOD);
return F.get(n);
}
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
while(con.hasNext())
{
long a = con.nextLong();
long b = con.nextLong();
long d = gcd(a,b);
System.out.println(fib(d));
}
con.close();
}
}