高速電力最適化テンプレート行列DP

 関連ブログ:https://blog.csdn.net/china_xyc/article/details/89819376#commentBox

行列の乗算は、対象DP上で最適化することができ、我々は、次の要件があります。

  1. だけ加算転送タイプ、等、減算をクリアし、最大と最小のに許可されていません
  2. 最初の数DP結果の伝達係数は一定でなければならない場合には
  3. 一般スーパーマルチにおける遷移の数
  4. 転送回数ので、一般的にINTの範囲内の弾性率を有します

要約すると、例:

DP [I] = A×DP [I-1] + DP×B [I-2] + C×DP [I-3]

ここで、A、B、Cの定数、及びDPの必要な行列の最適化、多くの場合、I 2 ^ 128等、特に鬼畜特に多数あり、
最適化された行列乗算は、DPを見つけるために[i]はOでありますタイムログ(i)が完成されます。
だから、どのように行列の乗算を達成するために、その原理はシェーンのですか?
行列乗算は、2つの行列AとBを必要とし、Aは、P×Nであり、Bは、以下に、M×Pの大きさであります

 

 

説明を容易にするために、我々は、フィボナッチ行為の例を与えます。
フィボナッチ伝達式は、DP [I] = DP [ I-1] + DP [I-2]。
我々次いで(DP [I]、DP [ I-1]) の1×2行列Aであるとみなす
行列Aを乗じた各時間はF .:転送することと等価である
|を。1. 1 |
| 0.1 |
結果である:(DP [I] + DP [I-1]、DP [i])と、 (DP [I + 1]であり、 DP [i])と
オリジナルながら一度8回必要な行列乗算演算、状態遷移が一度だけ必要なので、廃木材、それに行列乗算アルゴリズムが表示されません。
鍵です!行列の乗算は、関連性を持っている、ちょっとちょっとちょっと、我々はすぐにパワーアップを開始することができます!それを見て、このようにO(n)のアルゴリズムの最適化は、我々は、これが最適化された使用することができますnはフライドチキンフライドチキン大きな変態時に簡単なO(8×LOGN)アルゴリズムとなっています。

 

 

あなた自身の例が行う  https://www.luogu.org/problem/P5343

使用される知識:交差(ビット集合<N> =、および&)線形再帰(DP)のセット   マトリックス加速度マトリックスフラッシュパワー)(実際には、幾分スクロール・アレイのような)
線形再帰的な感じがある:F(N)= F(N-1)+ F (N-2)、 及び、値Fを知る(1)、F(2 ) 次に、Fの導入(3)の値、およびばなら再帰ダウン、それが行く上記の値を知っていることです私たちは、後者の値を知っています。

 

 

#include <cstdioを> 
する#include <CStringの> 
する#include <iostreamの> 
する#include <ビットセット> 
の#include <アルゴリズム>
 使用して 名前空間STDを、

typedefの長い 長いLL。
const  int型 MAXN = 105 ;
const  int型 MOD = 1E9 + 7 
LLのn; 
int型M、X。
ビットセット <MAXN> A、B; 
LL G [MAXN] [MAXN]、TMP [MAXN] [MAXN]、RES [MAXN] [MAXN]。
【MAXN] DP LL。

ボイド{([] [MAXN]、LL B [] [MAXN] LL)MULT 
    のmemset(TMP、0はsizeof(TMP))。
    以下のためにint型 i = 1 ; iは= < 100 ; iは++ ){
         ためint型の J = 1 ; J <= 100 ; J ++ ){
             ためのint型のk = 1 ; K <= 100 ; ++ k個){ 
                TMP [I] [ J] =(TMP [I] [J] + [I] [K] * B [k]は[J]%のMOD)%MOD。
            } 
        } 
    } 
    のためにint型 i = 1 ; iは= < 100 ; iは++ ){
         ためINTJ = 1 ; J <= 100 ; J ++ ){ 
            [I] [J] = TMP [I] [J]。
        } 
    } 
} 

ボイドqpow {([] [MAXN]、LL N LL)
    のmemset(RES、0はsizeof (RES))。
    以下のためにint型 i = 1 ; iは= < 100 ; iは++ ){ 
        RES [i]は[I] = 1 
    } 
    一方、(N){
         場合(N - 1 )MULT(RES、A)。
        MULT(A)。
        N = >> 1 
    }
    以下のためにint型私= 1 ; iが= < 100 ; iが++ ){
         ためINT J = 1 ; J <= 100 ; J ++ ){ 
            [I] [J] =のRES [I] [J]。
        } 
    } 
} 

int型のmain(){ 
    scanf関数(" %のLLD%dの"、&​​N、&M)。
    以下のためにint型私= 0 ; iが<M; iが++ ){ 
        scanf関数(" %のD "、&x)は、
        [X] = 1
    } 
    のscanf(" %dの"、&M)。
    以下のためにint型私= 0 ; iが<M; iが++ ){ 
        scanf関数(" %のD "、&x)は、
        B [X] = 1 
    } 
    A&= B。

    以下のためにint型 i = 1 ; iは= < 100 ; iは++ ){
         場合([i])とG [ 1 ]、[I] = 1 
    } 
    のためにint型 I = 2 ; I <= 100; 私は++ ){ 
        G [i]は[I - 1 ] = 1 
    } 

    // DP [0] = 1。
    // ため(INT i = 0; iが<= 100; I ++){
     //      ため(INT J = 1; J <= I; J ++){
     //          もし([J]){
     //              DP [I] =(DP [I] + DP [IJ])%MOD。
    //          }
     //      }
     // }
     // 場合(N <= 99)のprintf( "%Dを\ n"、DP [N])。
    // 他{
     //      qpow(G、N-99)。
    //      LL ANS = 0;
    //      ため(INT i = 1; iは= 100 <; iは++){
     //         = ANS(ANS + DP [I-100] * G [I]%MOD [1])MOD%;
     //      }
     //      のprintf( "%LLDの\のN-"、ANS);
     // } 

    // 元の直接マトリックスF(1)= 0であるため、高速電力ああ..、最初の直接作ることができる 
    qpow(G、N- 0 ); 
    (printfの" %LLDの\のN- " [Gを1 ] [ 1 ]) ; 
}

 

おすすめ

転載: www.cnblogs.com/-Zzz-/p/11483220.html