行列の乗算(IV):、再帰的な決定、問題を分析し、高速電力解決行列を使用して

      迅速なアプリケーションマトリックス電力動作は、問題の再発を解決することができます。実際には、対象者が直接、再帰与える慎重に迅速な問題解決を加速問題を分析し、再帰的に識別して、マトリックス電力動作を使用する必要はありません時々あります。

[実施例1]プログラム読解。

      以下のC言語プログラム:

する#include <stdio.hの>
int型のmain()
{
     int型N、M、F、I。
     一方、(!のscanf( "%d個の%のD"、&N、&M)= EOF)
     {
           F = 0。
           用(i = 1; iが<= N; iが++)
           {
                IF(I&1)F =(F * 2 + 1)%のM。
                そうでなければF = F * 2%M。
           }
           のprintf( "%d個の\ n"、F)。
     }
     0を返します。
}

       上記の手順、Mを読み取り、n個の入力に応じて、プログラムの実行結果を書き込むこと。例えば、入力310は、出力が5であるべきです。

       しかしながら、nおよびmのデータ範囲への入力1 <= N、M <= 1000000000、およびテストセットで大量のデータを与えられているので、所定のプログラムを直接意志タイムアウトを提出している場合。あなたはn個の入力に応じて、プログラムを書いて、すばやく特定のプログラム機能を実現するために、問題を解決するmは。

      (1)アイディアをプログラミングします。

      所与のブロックは、実際には反復的方法によってF(N)%mを評価します。計算のF(N)メソッドを見つけ、余り考慮されていません。

      所与の既知のプログラム、F(0)= 0、nが奇数である、F(N)= 2 * fの分析(N-1)+1; nが偶数、(N)F = 2 * fが(ある場合N-1)。

      以下のさらなる分析は、統一された再帰のn個のパリティを考慮していました。

       nが奇数の場合、F(N)= 2 * fは(N-1)+ 1、N-1が偶数、F(N-1)= 2 * F(N-2)でなければなりません。そのため、

                F(N)= F(N-1)+ F(N-1)+ 1 = 2 * F(N-2)+ F(N-1)+1。

       nがN-1常に奇数、F(N-1)= 2 * F(N-2)+1偶数、(N)F = 2 * F(n-1)は、ある場合。そのため、

                F(N)= F(N-1)+ F(N-1)= 2 * F(N-2)+ F(N-1)+1。

      したがって、均一な再帰式を得た:F(0)= 0、F(1)= 1、(N)F = 2 * F(N-2)+ fは(N-1)+1(N> = 3)。

      漸化式を決定した後、行列Pは、高速べき乗を解決するために、構成することができます。

       

      

 

      

 

       (2)ソース。

する#include <stdio.hに>
する#include <string.hの>
構造体マトリックス
{
      __int64マット[4] [4]。//存储矩阵中各元素
}。
マトリックスMATMUL(、マトリックスBをマトリックス、整数nは、INTのM)
{
      行列C。
      memset(c.mat、0、はsizeof(c.mat))。
      int型I、J、K。
      ため(K = 1; K <= N; ++ k)の
          ための式(I ++はi = 1; iが<= N)
              であれば(!a.mat [I] [K] = 0)
                  J <=(J = 1 N; J ++)
                      c.mat [I] [J] =(c.mat [I] [J] + a.mat [I] [K] * b.mat [K] [J])%のM。
      Cを返します。
}
マトリックスquickMatPow(、INT mを整数bを行列、INT N)// N阶矩阵快速Bの次幂
{
      行列C。
      memset(c.mat、0、はsizeof(c.mat))。
      私はint型。
      用(i = 1; iが<= N; iは++)
           c.mat [i]は[I] = 1。
      一方、(B!= 0)
      {
           IF(B&1)
               C = MATMUL(C、N、M)。// C = C *;
           = MATMUL(N、M)。// A = A *
           B / = 2;
      }
      Cを返します。
}
int型のmain()
{
      int型N、M。
      __int64 ANS;
      行列P;
      (!のscanf( "%d個の%のD"、&N、&M)= 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。
            IF(N <3)
                 のprintf( "%d個の\ n"、N%のM)。
           そうでなければ
           {
                 P = quickMatPow(P、3、N-2、M)。
                 年間= p.mat [2] [1]%のM。
                 YR =(+ p.mat年[2] [2] * 2)%のM。
                 YR =(+ p.mat年[2] [3])%のM。
                 printf( "%I64dの\ n"は、年);
          }
      }
      0を返します。
}

[実施例2]すべてのライトオフ。

       最初に完全に点灯している列に配置されたランプ、第1ランププレス(プレス後の状態を変更)は、nが存在します。次いで、すべてのライトオフ最初のk及びk + 1番目の光場合、K + 2の光がプレスすることができます。少なくとも、あなたはすべてのライトを退治したいどのように多くの手順尋ねますか?

      例えば、N = 2、2 HOを必要とします。最初の二つの光は、HO、HOは第二のライトを駆除退治します。n = 3の場合、5 HO必要。HOは、第一光及び第二の光HO根絶3,3 1つのHO照明光(点灯消灯注1、2が点灯から直接することができない)、第2号HO駆除を駆除します光、5つのHO駆除が点灯します。

      (1)アイディアをプログラミングします。 

       F [n]とを集合Nの完全な明るい光が、ランプは全点灯に必要なステップの最小数となる消灯表してもよいオフフル、フルNに必要なステップの最小数になる表します。 
      1)最後のランプを駆除するために、フロントライト、N-2(N-1ライトが上に留まる)根絶しなければならない、[N-2] +1 Fいくつかのステップを必要とします。 
      2)n-1個のライトを駆除するため、N-2に第2のバックライトランプをさせる必要があり、N-2バックライトランプのために、背面上のn-3光のせなければなりません。 ..、N-2すべきすなわち光が再びオンされる前に、F必要なステップの数[N-2]。 
      3)フロントN-2バックライトランプの後に、N-1を離れる前にライトは、明るいすなわち、残りのタスクは、光が出て行くのn-1を置くことで、fは必要なステップの数[N- 1]。 
      要約する:F [N] = 2 * F [N-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(、行列B、INT nの行列)
{
      行列C。
      memset(c.mat、0、はsizeof(c.mat))。
      int型I、J、K。
      ため(K = 1; K <= N; ++ k)の
          ための式(I ++はi = 1; iが<= N)
              であれば(!a.mat [I] [K] = 0)
                  J <=(J = 1 N; J ++)
                      c.mat [I] [J] =(c.mat [I] [J] + a.mat [I] [K] * b.mat [K] [J])%MOD。
      Cを返します。
}
マトリックスquickMatPow(行列、整数nは、INT b)は// N阶矩阵快速Bの次幂
{
      行列C。
      memset(c.mat、0、はsizeof(c.mat))。
      私はint型。
      用(i = 1; iが<= N; iは++)
            c.mat [i]は[I] = 1。
      一方、(B!= 0)
      {
           IF(B&1)
                C = MATMUL(C、N)。// C = C *;
           = MATMUL(、N)// A = A *
           B / = 2;
      }
      Cを返します。
}
メインINT()
{
      int型のn;
      __int64 ANS;
      行列P;
      (!のscanf( "%d個"、&N)&& N = 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。
           IF(N <3)
               printf( "%d個の\ n"、N%MOD)。
           そうでなければ
           {
                P = quickMatPow(P、3、N-2)。
                ANS =(p.mat [1] [1] * 2 + p.mat [1] [2] + p.mat [1]〜[3])%MOD。
                printf( "%I64dの\ n"、ANS)。
           }
      }
      0を返します。
}

おすすめ

転載: www.cnblogs.com/cs-whut/p/11456718.html