2414. Сумма квадратов
Обозначим через
U(n) общее количество
последовательностей, состоящих только
из чисел 1 и 2, сумма членов которой,
равна n.
По заданному
значению n определите сумму квадратов
чисел U(i) для всех i = 1, …, n.
Результат выведите по модулю 109 + 9.
Вход. Одно натуральное число n (1 ≤ n ≤ 1018).
Выход. Выведите
значение mod (109 + 9).
Пример
входа |
Пример
выхода |
3 |
14 |
числа
Фибоначчи
Рассмотрим, что
собой представляет функция U(n). Очевидно,
что U(1) = 1 (одна последовательность из одной единицы), U(2) = 2 (две
последовательности 1, 1 и 2). Для всех натуральных n U(n) соответствует
рекуррентности Фибоначчи:
Например, для начальных
значений n можно получить следующие
последовательности:
Числа Фибоначчи
имеют следующий вид:
В задаче
требуется найти сумму
U(1)2
+ U(2)2 + … + U(n)2
= F(2)2 + F(3)2 + … + F(n+1)2 = F(n+1)
* F(n+2) – 1
Осталось
реализовать вычисление чисел Фибоначчи F(n) за время O(log2n).
Сумма квадратов
чисел Фибоначчи имеет геометрическую интерпретацию. Составим прямоугольник из
квадратов с длинами сторон F(1), F(2), …, F(n) как показано на рисунке. Тогда площадь
прямоугольника равна F(n) * F(n + 1).
F(1)2
+ F(2)2 + F(3)2 + F(4)2 + F(5)2 + F(6)2 =
12 + 12 + 22
+ 32 + 52 + 82 = 8 * 13 = F(6) * F(7)
Таким образом
F(1)2
+ . . . + F(n)2 =
F(n) * F(n + 1)
Эту формулу
можно доказать при помощи метода математической индукции:
1. База
индукции: n = 1. F(1)2 = F(1) * F(2) или 12 =
1 * 1, что верно.
2. Шаг индукции.
F(1)2
+ . . . + F(n)2 +
F(n + 1)2 =
F(n) * F(n + 1) + F(n + 1)2 =
= F(n + 1) * (F(n) + F(n + 1)) = F(n + 1) * F(n + 2)
Пример
Для n = 3 имеем:
U(1)2
+ U(2)2 + U(3)2 =
F(2)2
+ F(3)2 + F(4)2 = F(4) * F(5) – 1 = 3 * 5 – 1 = 14
Объявим модуль
MOD, вычисления по которому будем производить.
#define MOD 1000000009
Реализуем вычисление чисел Фибоначчи через возведение матрицы
в степень.
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;
}
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;
}
Matrix operator^ (long long n)
{
Matrix x(*this);
if (n == 0) return Matrix();
if (n & 1) return x * ((x * x) ^ (n / 2));
return (x * x) ^ (n / 2);
}
};
long long fib(long long n)
{
Matrix res(1, 1, 1, 0);
res = res ^ n;
return res.b;
}
Читаем входные данные, вычисляем и
выводим результирующее значение Fn+1
* Fn+2 – 1.
scanf("%lld",&n);
res = (fib(n+1)
* fib(n+2) + MOD - 1) % MOD;
printf("%lld\n",res);
#include <cstdio>
#include <map>
#define MOD 1000000009
using namespace std;
map<long long, long long> fib;
long long f(long long n)
{
if (n == 0) return 1;
if (n == 1) return 1;
if (fib[n] != 0) return fib[n];
long long k = n / 2;
if (n % 2 == 0)
return fib[n] = (f(k - 1) * f(k - 1) + f(k) * f(k)) % MOD;
return fib[n] = (f(k) * (f(k - 1) + f(k + 1))) % MOD;
}
long long n, res;
int main(void)
{
scanf("%lld", &n);
res =
(f(n) * f(n + 1) + MOD - 1) % MOD;
printf("%lld\n", res);
return 0;
}