Быстрая матрица приложения операция питания может решить проблему повторения. На практике это иногда субъект непосредственно не дает рекурсивным, необходимо тщательно проанализировать проблемы и определить рекурсивно, а затем использовать операцию матрицы питания быстро ускорить решение проблемы.
[Пример 1] Программа понимание чтения.
В следующей программе на языке C:
# include <stdio.h>
INT основных ()
{
Int N, M, F, I;
в то время как (Scanf ( "% D% D", & п, & м) = EOF!)
{
е = 0;
для (я = 1; г <= п; я ++)
{
если (я & 1) F = (F * 2 + 1)% м;
то F = F * 2% м;
}
Е ( "% d \ п", е);
}
Возвращает 0;
}
Чтение описанной выше процедуры, т и п в соответствии с входом, чтобы записать результаты выполнения программы. Например, вход 310, выход должен быть 5.
Однако из-за диапазон данных п и т дается вход 1 <= п, т <= 1000000000, а также большое количество данных в тестовом наборе, так что если данная программа непосредственно будет представлен тайм-аут. Вы пишете программу, в соответствии с входным п и м быстро решить эту проблему, для достижения данной функции программы.
(1) программирование идеи.
Данный блок фактически оценивается F (п)% м итерационным способом. Не считается Остаток, найти (п) метод расчета ф.
Анализ данной программы, известной, F (0) = 0, когда п нечетно, ф (п) = 2 * F (п-1) + 1; когда п является четным числом, ф (п) = 2 * F ( н-1).
Следующий дальнейший анализ, найдено не рассматривать п четность единой рекурсивной.
При нечетном п, Р (п) = 2 * F (п-1) + 1, п-1 должно быть четным числом, е (п-1) = 2 * F (п-2). Таким образом,
е (п) = е (п-1) + F (п-1) + 1 = 2 * F (п-2) + F (п-1) +1.
При п является четным числом, ф (п) = 2 * F (п-1), п-1 всегда нечетное число, е (п-1) = 2 * F (п-2) + 1. Таким образом,
е (п) = е (п-1) + F (п-1) = 2 * F (п-2) + F (п-1) +1.
Таким образом, чтобы получить равномерную рекурсивную формулу: F (0) = 0, F (1) = 1, F (N) = 2 * п (п-2) + F (п-1) + 1 (п> = 3).
После определения рекуррентной формулы, матрица Р может быть сконфигурирован, для решения быстрого возведения в степени.
(2) источник.
#include <stdio.h>
#include <string.h>
структура матрицы
{
__int64 мат [4] [4]; //存储矩阵中各元素
};
Матрица matMul (матрица А, матрица В, Int N, Int м)
{
Матрица с;
MemSet (c.mat, 0, SizeOf (c.mat));
Int я, J, K;
для (к = 1, K <= N; K ++) ,
для (я = 1; г <= п; я ++) ,
если (a.mat [I] [к]! = 0)
для (J = 1, J <= п; j ++)
c.mat [I] [J] = (c.mat [I] [J] + a.mat [I] [к] * b.mat [к] [J])% м;
вернуться с;
}
Матрица quickMatPow (матрица А, Int N, Int B, Int м) // п阶矩阵快速б次幂
{
Матрица с;
MemSet (c.mat, 0, SizeOf (c.mat));
Int я;
для (я = 1; г <= п; я ++)
c.mat [I] [I] = 1;
в то время как (б! = 0)
{
если (б & 1)
с = matMul (с, а, п, т); // с = с * а;
а = matMul (а, а, п, т); // а = а * а
б / = 2;
}
Вернуться с;
}
INT основных ()
{
Int N, м;
__int64 ANS;
Матрица р;
в то время как (Scanf ( "% D% D", & п, & м) = EOF!)
{
MemSet (p.mat, 0, SizeOf (p.mat));
p.mat [2] [1] = 2;
p.mat [1] [2] = p.mat [2] [2] = 1;
p.mat [2] [3] = p.mat [3] [3] = 1;
если (п <3)
Е ( "% d \ N", N% м);
остальное
{
р = quickMatPow (р, 3, п-2, м);
лет = p.mat [2] [1]% м;
Yr = (+ p.mat года [2] [2] * 2)% м;
Yr = (+ p.mat года [2] [3])% м;
Е ( "% I64d \ п", год);
}
}
Возвращает 0;
}
[Пример 2] выключает все огни.
Есть п лампы расположена в ряде первоначально полностью освещено, первая лампа пресса (изменить состояние после нажатия). Если первый к тогда все выключенным светом и к + 1-й огни, огни к + 2 может быть пресса. По крайней мере, спросить, сколько шагов вы хотите, чтобы уничтожить все огни?
Так, например, п = 2, требует 2 хо. Первые два источника света истребить хо, хо истребить вторую фару. при п = 3, 5 хо потребность. Хо уничтожить первые огни и вторые огни хо истреблять 3, 3 1 хо осветительных огней (фары незажженного примечания 1, 2 не может быть непосредственно от света), четвертый № 2 хо Exterminate свет, 5 хо истребить огни.
(1) программирование идеи.
Установите F [N] и п представляет собой полный яркий свет становится минимальным количеством шагов , необходимыми для полного выключения, полного п также может представлять собой погашена лампа станет минимальным количеством шагов , необходимых для полного освещения.
1) для того , чтобы уничтожить последнюю лампу, нужно уничтожить передние фары N-2 (N-1 горит остаться на), требуют несколько шагов F [N-2] +1.
2) для того , чтобы уничтожить N-1 свет, п-2 должно позволить второй заднему свет лампы, п-2 задних световых ламп, должно позволить н-3 огней обратно. .. п-2 должен т.е. перед тем огни снова включен, число требуемых шагов F [п-2].
3) фронт п-2 после того, как задняя подсветка ламп, прежде чем покинуть п-1 огни яркий, т.е., оставшаяся задача состоит в том, чтобы положить N-1 гаснет свет, количество шагов , требуемых F [н- 1].
Подводя итог: F [N] = 2 * п [п-2] + F [N-1] + 1. (N> = 3) F [ 1] = 1, F [2] = 2.
(2) источник.
#include <stdio.h>
#include <string.h>
#define MOD 200907
структура матрицы
{
__int64 мат [4] [4]; //存储矩阵中各元素
};
Матрица matMul (матрица А, матрица В, Int N)
{
Матрица с;
MemSet (c.mat, 0, SizeOf (c.mat));
Int я, J, K;
для (к = 1, K <= N; K ++) ,
для (я = 1; г <= п; я ++) ,
если (a.mat [I] [к]! = 0)
для (J = 1, J <= п; j ++)
c.mat [I] [J] = (c.mat [I] [J] + a.mat [I] [к] * b.mat [к] [J])% MOD;
вернуться с;
}
Матрица quickMatPow (матрица А, Int N, Int б) // п阶矩阵快速б次幂
{
Матрица с;
MemSet (c.mat, 0, SizeOf (c.mat));
Int я;
для (я = 1; г <= п; я ++)
c.mat [I] [I] = 1;
в то время как (б! = 0)
{
если (б & 1)
с = matMul (с, а, п); // с = с * а;
а = matMul (а, а, п); // а = а * а
б / = 2;
}
Вернуться с;
}
INT основных ()
{
Int N;
__int64 ANS;
Матрица р;
в то время как (Scanf ( "% D", & п) && п! = 0)
{
MemSet (p.mat, 0, SizeOf (p.mat));
p.mat [1] [2] = 2;
p.mat [1] [1] = p.mat [1] [3] = 1;
p.mat [2] [1] = p.mat [3] [3] = 1;
если (п <3)
Е ( "% d \ п", п% MOD);
остальное
{
р = quickMatPow (р, 3, п-2);
ANS = (p.mat [1] [1] * 2 + p.mat [1] [2] + p.mat [1] [3])% MOD;
Е ( "% I64d \ п", ANS);
}
}
Возвращают 0;
}