Умножение матриц (IV): проанализировать проблему, определить рекурсивно, используя быстрый мощностной решения матрицы

      Быстрая матрица приложения операция питания может решить проблему повторения. На практике это иногда субъект непосредственно не дает рекурсивным, необходимо тщательно проанализировать проблемы и определить рекурсивно, а затем использовать операцию матрицы питания быстро ускорить решение проблемы.

[Пример 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;
}

рекомендация

отwww.cnblogs.com/cs-whut/p/11456718.html
рекомендация