アプリケーションの概要にDPクラス行列の最適化問題

序文

上のBenpian重視のアプリケーションの基礎、行列は(多分...に基づいて記事を書くために)省略されています。

イデオロギーと原則

なぜOier我々はDP行列、それをスピードアップするために考えることができますか?いくつかのDP&Aを行った後、我々はDPが2つの間にその時々二状態転送ができます向ける固定された状態のため、DP転送のすべての段階で、つまり、\(F_iと\)のみを、状態の一定のセットに転送することができる(\ \ {F_iと\} \ ) 、我々は、転写の位相が変更される変更されない方向に。

まあ、キー情報を抽出し、我々は状態を転送する必要があり、状態遷移と同じように(がんの問題のいくつかを排除していない)、およびほとんどの転送のために、様々な状態の操作の間のバンド係数よりも何もありません。あまりにも多くの時間とは、あなたが州の小さな数を移動する必要があるとき、私たちは、電源の高速転送を最適化するために、マトリックスの使用を考慮することができます。

高速電力チーズバーの現在のセットの原理と実装マトリックス、少し少し〜

もちろん、あなたはまだ、その後、様々な状態DP式の関係を観察した後、状態遷移行列を持つラインを構築し、その後、すぐに電源を投入することができ、DPの簡単な式で開始する必要があり、すべての最初の、DPを最適化するために行列を使用する必要がある場合。

一般的なルーチン

  • テンプレートなどのstructパッケージのマトリックスを使用するなど、;個人は、転送行列構造XDの左側に配置する傾向があります。
  • マトリックスが加速推測いくつかの能力であるべきであるoierしなければならない各データ範囲YYに面します。
  • カスタムマトリックス乗算、我々は、それが満足して、特定の状態遷移のために知っておく必要があります一般的な行列の乗算の基本的な性質を、我々はまた、加速する行列を使用することができ、次の例では、これは適切な方法です。
  • 前処理アウト違法転送行列を、こんにゃくの最適化問題は、すべての約半分押し形状に関係しています,,,その後、我々は前の状態自体は違法ではありませんどの把握することができ、その後、行列の要素を減らす(行列がされる(\ O(N ^ 3)\)ああ)。
  • 遷移マトリクスアレイを構築するための支援を提供し、CSPはとにかく,,,右のような問題悪性腫瘍を認識し、それをテストするために、この困難であってはなりません。
  • 話題の特殊な治療のための特定の要件実際には、それにはない特別な取引は、タイトルにすべての条件を置く方法であるが、内部のマトリックスに設計されていますので、漏れません。

私は追加することだと思います。

牛の牛リレーリレー

図最短エッジを介してS K Eを求め、無向を与え。

この質問は非常に裸の行列の最適化であることを、フロイドのアルゴリズムのための十分な深さの言葉を理解し、私たちは、行列の乗算を再定義する必要がある、と一般化行列の乗算のすべてのプロパティの遵守を証明しなければならない。場合

コークス

ちょっと質問の意味。

少し難しいです。

課題は、マトリックスへのデザインの条件に我々は合理的に対象行う方法です。

チェス盤

ちょっと質問の意味。

次いで約プレス、マイナス冗長状態とを有するようなマトリックスの転送を最適化します。

ガーデン

ちょっと質問の意味。

そして、前の質問のように、しかし状態に困難が大きなポイントを表します。

この質問はそれが前に考えないされ、動物園加速状態間の移行は連続的かつ非常に短いので、自然な圧力のように考える、のアプローチ、および各状態は状態に転送することができます決定され、そしてすべての行列を考えます転送。

すべての事前の法的転送例したがって、最初の、そして解決するための高速行列のパワーを指示。

コードは、私を参照してくださいブログ

強迫性障害のためGXOI / GZOI2019の死刑判決

タイトル効果:で\(2 \回N \)を有する正方形\(N-1 \)ブロック\(2 \回1 \)のタイル、および\(2 \)ブロック\(1 \回1 \ )満たされたタイルの、および2 \(1 \回1 \)四角は、隣接する側面を持つことができない、いくつかの合法的なプログラムを見つけます。

言わなければならない、この質問は本当に疲れて、あなたは大きな波動方程式をプッシュする必要があります。

この質問は、私たちは、私たちは内部に状態遷移行列の設計を支援するための補助アレイの使用を検討する必要があります。

おそらく、ここでより良い経験を持って読むには?

ああ、カウントが、私はそう思うようになりました。

あなたはその方法で取得しない場合、我々は簡単に考えることができ、2個のレンガです\(F [I] = F [I-1] + Fの[I-2] \) 離れてからの再帰的。

まあ、今2を見て邪魔にレンガの。

まず、我々は2つの特定のブリックがグリッド全体三つの部分に分割することが見出され、我々は、左と右の部分がちょうど完了したと仮定する(即ち、矩形)、そこ中間ブロックの特性を示します。

2枚、特殊ブロックの奇数は、二つのブロックは、2つの別個の行になければならない唯一のプログラム要素及び中間離間しているときに注意深く押し、でしょう。

同様に、二枚は、二つの同じ行のブロック、及び中間構成でなければならない特別なブロックの偶数、唯一のアプローチを間隔を置いて配置されます。

隣接する側面がないためと、その式が出てきました。
\ [回答= 2 * \ sum_
{i = 0} ^ {N-3} \ sum_ J [F {J = 0} ^ {I}] * [IJ] \ f]の薄い理解。

おそらくこれだけ使用する必要があります\(20pt \)を、我々は、最適化する方法を考えますか?参照してください\(N \ル2E + 9 \) のデータ範囲は、もちろん、すぐに行列パワーの少し上に行きたいです。

まあ、私はしません

外挿行列は、我々はこの式を解体段階的に行かなければならない、それを変えます。

\(G(I)= \ sum_ {J = 0} ^ {I} F(J)* F(IJ)\)

そう

\(\開始{式} \開始{整列} G(I)&= \ sum_ {J = 0} ^ {I} F(J)* F(IJ)\\&= \ sum_ {J = 0} ^ {I-2} F(J)*(IJ)F + F(I-1)* F(1)+ F(I)* F(0)\\&= \ sum_ {J = 0} ^ {I -2} F(J)* [F(I-1-J)+ F(I-2-J)] + F(I-1)+ F(I)\\&= G(I-2)+ G(I-1)+ F(I)\端{整列} \端{式} \)

又设\(和(I)= \ sum_ {J = 0} ^ {I} G(J)\)

そう

\(\開始{式} \ {整列}和(i)を開始&= \ sum_ {J = 0} ^ {I} G(J)\\&= \ sum_ {J = 0} ^ {I-1} G(J)+ G(I)\\&= SUM(I-1)+ G(I-2)+ G(I-1)+ F(I)\端{整列} \端{式} \)

そう簡単にプッシュ行列は、方程式を転送する必要があります。

(\ \ \ {{式}始める[\開始{アレイ} {CCC} 1・1・0 0 0 \\ 1&0 0 0 0 \\ 1・1・1・1・0を残し端{アレイ} \ \\ 0 0 1&0&0 \\ 1・1・1・1・1 \\ \右]}回{CCC} F(I {\は[\開始{アレイを左} \ )\\ F(I-1)\\ G(I)\\ G(I-1)\\和(I)\\ \端{アレイ} \右]} = {\ [\ {アレイを開始左} {CCC} F(I + 1)\\ F(I)\\ G(i + 1)の\\ G(I)\\和(I + 1)\端{アレイ} \右]} \端{式} \)

したがって、\(O(125logn)\)を超えることができます。

下界プロセスことに注意してください。

コード:

#include<ctime>
#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int MAX = 100000 + 5;
const int mod = 1e9 + 7;
inline int read(){
    int f = 1, x = 0;char ch;
    do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0'||ch>'9');
    do {x = x*10+ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); 
    return f*x;
}

struct sakura {
    ll mar[5][5];
}A;

int t, n;

inline sakura mul(sakura A, sakura B) {
    sakura C;
    memset(C.mar, 0, sizeof (C.mar));
    for (int i = 0;i <= 4; ++i) {
    for (int k = 0;k <= 4; ++k) {       
        for (int j = 0;j <= 4; ++j) {
                C.mar[i][j] = (C.mar[i][j] + (A.mar[i][k] * B.mar[k][j]) % mod ) % mod;
            }
        }
    }
    return C;
}

inline sakura mi(sakura A, int c) {
    sakura B;
    B.mar[0][0] = 1, B.mar[1][0] = 1, B.mar[2][0] = 2, B.mar[3][0] = 1, B.mar[4][0] = 3;
    for (;c;c >>= 1) {
        if (c & 1)  B = mul(A, B);
        A = mul(A, A);
    }
    return B;
}
int main(){
    t = read();
    while (t--) {
        n = read();
        if (n < 3) {
            printf("0\n");
            continue;
        }
        if (n == 3) {
            printf("2\n");
            continue;
        }
        A.mar[0][0] = 1, A.mar[0][1] = 1, A.mar[0][2] = 0, A.mar[0][3] = 0, A.mar[0][4] = 0;
        A.mar[1][0] = 1, A.mar[1][1] = 0, A.mar[1][2] = 0, A.mar[1][3] = 0, A.mar[1][4] = 0;
        A.mar[2][0] = 1, A.mar[2][1] = 1, A.mar[2][2] = 1, A.mar[2][3] = 1, A.mar[2][4] = 0;
        A.mar[3][0] = 0, A.mar[3][1] = 0, A.mar[3][2] = 1, A.mar[3][3] = 0, A.mar[3][4] = 0;
        A.mar[4][0] = 1, A.mar[4][1] = 1, A.mar[4][2] = 1, A.mar[4][3] = 1, A.mar[4][4] = 1;
        sakura ans = mi(A, n - 4);
        ans.mar[4][0] <<= 1;
        ans.mar[4][0] %= mod;
        printf("%d\n", ans.mar[4][0]);
    }
    return 0;
}

深い読み

おすすめ

転載: www.cnblogs.com/silentEAG/p/11589939.html