算法 {矩阵DP(矩阵优化递推DP)}

算法 {矩阵DP(矩阵优化递推DP)}

矩陣DP

定义

有個若干個DP (比如有3個DP: DP0[ N], DP1[ N], DP2[ N]), 每一個DP的遞推式 滿足線性組合, 即 D P 0 / 1 / 2 [ i ] = k 1 ∗ D P 0 [ i − 1 ] + k 2 ∗ D P 1 [ i − 1 ] + k 3 ∗ D P 2 [ i − 1 ] DP0/1/2[ i] = k1*DP0[ i-1] + k2*DP1[i-1] + k3*DP2[i-1] DP0/1/2[i]=k1DP0[i1]+k2DP1[i1]+k3DP2[i1];

for( int i = 1; i < N; ++i){
	DP0[ i] = k0*DP0[ i-1] + k1*DP1[ i-1] + k2*DP2[ i-1];
	DP1[ i] = k3*DP0[ i-1] + k4*DP1[ i-1] + k5*DP2[ i-1];
	DP2[ i] = k6*DP0[ i-1] + k7*DP1[ i-1] + k8*DP2[ i-1];
}

這個時間是 O ( N ) O(N) O(N)的, 如果 N N N很大 比如 > 1 e 8 >1e8 >1e8 那麼可以把以上過程 轉換為 矩陣乘法;

DP[3] = { DP0[0], DP1[0], DP2[0]}; (初值)
A[3][3] = { {k0, k3, k6}, {k1, k4, k7}, {k2, k5, k8}};

可以發現 執行矩陣乘法`DP * A = DPP` 會得到DPP[0]=DP0[1] DPP[1]=DP1[1] DPP[2]=DP2[1];
換句話說 `* A`表示: 進行了一次DP的遞推 (即對應樸素算法的for循環);
因此 要得到樸素算法的DP?[ N-1] 即進行了`N-1`次的遞推, 即`DP * A*...*A`(一共有N-1個A);

根據*矩陣乘法*的傳遞律, 比如你要進行5個遞推 那麼他等價於`(DP*A)*(A*A*A*A)`
因此`DP * A^n` 可以用快速冪計算, 有以下两种做法:  
1: 你可以先求出`AA: A^n`, 然後最後執行DP*AA;
2: DP也可以直接參與到快速冪裡, 即`DP*(A^1) * (A^2) * (A^4) * ...`;

错误

比如要快速幂求A^k, 最初答案矩阵 设置成全1 这是错误的!
矩阵乘法中的单位1 即单位矩阵, 不是全1, 而是主对角线为1 其他为0;

性质

算法

代碼

//{ ___DP_MatrixMultiply (矩阵优化递推DP)
template< class _T_> std::vector< _T_> ___DP_MatrixMultiply( std::vector<_T_> _initDP, std::vector<std::vector<_T_> > _factor, long long _count){
//< 比如`initDP = [DP0, DP1], factor: [[a,b], [c,d]]`, 则表示DP递推式为`DP0 = a*DP0 + b*DP1, DP1 = c*DP0 + d*DP1`;
//  . `_count`为递推次数, 即`initDP`进行`count`次递推后 结果为*返回值*;
    ASSERT_( _count >= 0, _count);
    ASSERT_( _initDP.size()==_factor.size() && _factor.size()==_factor[0].size());
    int const N = _initDP.size();
    { // `factor`转换为其转置矩阵
        for( int i = 0; i < N; ++i){
            for( int j = i+1; j < N; ++j){
                std::swap( _factor[i][j], _factor[j][i]);
            }
        }
    }
    auto temp1 = _initDP;
    auto temp2 = _factor;
    while( _count > 0){
        if( _count & 1){ // DP *= factor;
            for( int col = 0; col < N; ++col){
                temp1[ col] = 0;
                for( int i = 0; i < N; ++i){
                    temp1[ col] += (_initDP[ i] * _factor[ i][ col]);
                }
            }
            _initDP = temp1;
        }
        _count >>= 1;
        { // factor *= factor
            for( int row = 0; row < N; ++row){
                for( int col = 0; col < N; ++col){
                    temp2[ row][ col] = 0;
                    for( int i = 0; i < N; ++i){
                        temp2[ row][ col] += (_factor[ row][ i] * _factor[ i][ col]);
                    }
                }
            }
            _factor = temp2;
        }
    }
    return _initDP;
}
//} ___DP_MatrixMultiply

例题

@LINK: https://editor.csdn.net/md/?not_checkout=1&articleId=139273191;
4.....4(长度为1e9)这个10进制数的取模值;
DP矩阵里 放一个常数;

@DELI;

@LINK: https://editor.csdn.net/md/?not_checkout=1&articleId=132818193;`;

@DELI;

AcWing-1305. GT考试

AcWing-1304. 佳佳的斐波那契

AcWing-1303. 斐波那契前 n 项和

筆記

The nature of Matrix-Multiplication in Algorithm is D P DP DP, so it is vital to review some notion of D P DP DP:
0 T i m e ( O r d e r ) Time(Order) Time(Order), the DP-Value of Time- i i i ( D P [ i ] DP[i] DP[i]) always depends on D P [ < i ] DP[<i] DP[<i];
. . For example, F i b o n a c c i [ i ] = F i b o n a c c i [ i − 1 ] + F i b o n a c c i [ i − 2 ] Fibonacci[i] = Fibonacci[i-1] + Fibonacci[i-2] Fibonacci[i]=Fibonacci[i1]+Fibonacci[i2];
1 State, at every Time- i i i, D P DP DP has several S t a t e s States States;
. . e.g., D P [ n ] DP[n] DP[n] has just one-state ( D P [ i ] DP[i] DP[i]); D P [ n ] [ m ] DP[n][m] DP[n][m] has m m m-states D P [ i ] [ 0 , 1 , . . . , m − 1 ] DP[i][0,1,...,m-1] DP[i][0,1,...,m1];

@Delimiter

The Matrix-Multiplication in Algorithm must be in the form:
D p [ a 0 , a 1 , . . . , a n − 1 ] ∗ F a c t o r [ k 0 , 0 k 0 , 1 . . . k 0 , n − 1 . . . k n − 1 , 0 k n − 1 , 1 . . . k n − 1 , n − 1 ] = R e s u l t [ b 0 , b 1 , . . . , b n − 1 ] Dp[a_0, a_1,..., a_{n-1}] * Factor\begin{bmatrix} k_{0,0}& k_{0,1} & ... & k_{0,n-1} \\ ... \\ k_{n-1,0} & k_{n-1,1} & ... & k_{n-1,n-1} \end{bmatrix} = Result[b_0, b_1,..., b_{n-1}] Dp[a0,a1,...,an1]Factor k0,0...kn1,0k0,1kn1,1......k0,n1kn1,n1 =Result[b0,b1,...,bn1]

D p Dp Dp must be a 1 ∗ n 1 * n 1n Row-Matrix;
F a c t o r Factor Factor must be a n ∗ n n*n nn Square-Matrix;
Then, R e s u l t Result Result is a 1 ∗ n 1 * n 1n Row-Matrix;
We called D p , R e s u l t Dp, Result Dp,Result the  DP-Matrix \text{ DP-Matrix}  DP-Matrix

If we denote D p [ a 0 , a 1 , . . . , a n − 1 ] Dp[a_0, a_1,..., a_{n-1}] Dp[a0,a1,...,an1] as the DP-Time- i i i (i.e., D P [ i ] DP[i] DP[i]), then R e s u l t [ b 0 , b 1 , . . . , b n − 1 ] Result[b_0, b_1,..., b_{n-1}] Result[b0,b1,...,bn1] would be the DP-Time- i + 1 i+1 i+1 (i.e., D P [ i + 1 ] DP[i+1] DP[i+1]);
. More specifically, the phrase D p [ a 0 , a 1 , . . . , a n − 1 ] = D P [ i ] Dp[a_0, a_1,..., a_{n-1}] = DP[i] Dp[a0,a1,...,an1]=DP[i] means that, D P [ i ] DP[i] DP[i] has n n n S t a t e s States States a 0 , . . . , a n − 1 a_0, ..., a_{n-1} a0,...,an1;
. So, a i , b i a_i, b_i ai,bi denote the same DP-State, just the Time of a i a_i ai is k k k and the Time of b i b_i bi is k + 1 k+1 k+1;

Then, b i = C 0 ∗ a 0 + C 1 ∗ a 1 + . . . + C n − 1 ∗ a n − 1 b_i = C_0 * a_0 + C_1 * a_1 + ... + C_{n-1} * a_{n-1} bi=C0a0+C1a1+...+Cn1an1 where C i C_i Ci are all C o n s t a n t s Constants Constants;
. That is, b i bi bi is a Linear-Combination of all a i a_i ai;
. Cuz C i C_i Ci must be C o n s t a n t s Constants Constants, the DP-State-Transformation must be in the form of Linear-Combination (i.e., Constant * DP-State \text{Constant * DP-State} Constant * DP-State) (if not, that DP not fit the Matrix-Multiplication);
. . e.g., D P [ i ] = D P [ i − 1 ] ∗ D P [ i − 2 ] DP[i] = DP[i-1] * DP[i-2] DP[i]=DP[i1]DP[i2] is Infeasible;

The utmost point is to clarify the correspondence between The-Time of the matrix- D p [ . . . ] Dp[...] Dp[...] and The-Time of the DP of all its elements a i a_i ai;
. e.g., Calculate the S [ i ] = ∑ j = 1 i F [ j ] S[i] = \sum_{j = 1}^{i} F[j] S[i]=j=1iF[j] where F [ ] F[] F[] is the Fibonacci;
. . Suppose the DP-Time of the matrix D p [ . . . ] Dp[...] Dp[...] is i i i, and we let a 0 = F [ i ] , a 1 = F [ i + 1 ] , a 2 = S [ i ] a_0 = F[i], a_1 = F[i+1], a_2 = S[i] a0=F[i],a1=F[i+1],a2=S[i] (suppose these three values are already gained);
. . We need to update b i b_i bi correctly, that is, to determine those k i , j k_{i,j} ki,j in the matrix- F a c t o r Factor Factor;
. . Then, the matrix- R e s u l t Result Result would be The-Time i + 1 i + 1 i+1 (cuz the matrix- D p Dp Dp is Time- i i i); Therefore, b 0 b_0 b0 denotes F [ i + 1 ] F[i + 1] F[i+1], b 1 = F [ i + 2 ] b_1 = F[i + 2] b1=F[i+2], b 2 = S [ i + 1 ] b_2 = S[i + 1] b2=S[i+1];
. . We need to find the relation between a i , b j a_i, b_j ai,bj, so b 0 = a 1 b_0 = a_1 b0=a1, b 1 = a 0 + a 1 b_1 = a_0 + a_1 b1=a0+a1, b 2 = a 2 + a 1 b_2 = a_2 + a_1 b2=a2+a1; This is valid due to the form of every formula is Linear-Combination;

@Delimiter

Initially, if we set the matrix- D p [ . . . ] Dp[...] Dp[...] as DP-Time- 0 0 0, we wanna it to be DP-Time- i i i;
. That is, D p [ . . . ] ∗ F a c t o r ∗ F a c t o r ∗ . . . ∗ F a c t o r Dp[...] * Factor * Factor * ... * Factor Dp[...]FactorFactor...Factor where the number of F a c t o r Factor Factor is i i i; the result would be the DP-Time- i i i;
. Matrix-Multiplication satisfies the Combination-Property, then it can be transformed to D p [ . . . ] ∗ ( F a c t o r i ) Dp[...] * (Factor ^ i) Dp[...](Factori), we can use Binary-Exponentiation to solve it;

@DELI;

Property-0 \text{Property-0} Property-0

The elements a i a_i ai in the matrix- D p [ a 0 , a 1 , . . . ] Dp[a_0, a_1, ...] Dp[a0,a1,...] can be divided into two-types:
0 a i a_i ai is a DP-State; The value of a i a_i ai depends on the DP-Time of the matrix- D p [ . . . ] Dp[...] Dp[...] (of course, a i a_i ai is not a Constant);
1 a i a_i ai is a Constant; Whatever the DP-Time of the matrix- D p [ . . . ] Dp[...] Dp[...] is, a i a_i ai is always the same;

For example, d p [ i ] = 2 ∗ d p [ i − 1 ] + 5 dp[i] = 2 * dp[i - 1] + 5 dp[i]=2dp[i1]+5, then we transform it to 2 ∗ d p [ i − 1 ] + 1 ∗ 5 2 * dp[i - 1] + 1 * 5 2dp[i1]+15 which satisfying the requirement that 2 , 1 2,1 2,1 are Constants;
. Let the matrix- D p [ a , b ] Dp[a,b] Dp[a,b] be the DP-Time- i i i where a = d p [ i ] , b = 5 a = dp[i], b = 5 a=dp[i],b=5;
. Then the matrix- R e s u l t [ c , d ] Result[c,d] Result[c,d] be the DP-Time- i + 1 i+1 i+1 where c = d p [ i + 1 ] = 2 ∗ d p [ i ] + 5 , d = 5 c = dp[i+1] = 2 * dp[i] + 5, d = 5 c=dp[i+1]=2dp[i]+5,d=5, so c = 2 ∗ a + 1 ∗ b , d = b c = 2 * a + 1 * b, d = b c=2a+1b,d=b satisfying the Linear-Combination;

@Delimiter

Property-1 \text{Property-1} Property-1

Once the DP-Time of the matrix- D p [ . . . ] Dp[...] Dp[...] is settled (suppose it is i i i), then the DP-Time of all its DP-Elements a i a_i ai is also fixed;
. e.g., Let the DP-Time of the matrix- D p [ a , b , c , d ] Dp[ a, b, c, d] Dp[a,b,c,d] is i i i, where a = d p 1 [ i ] , b = d p 2 [ i − 1 ] , c = d p 3 [ i + 1 ] a = dp_1[i], b = dp_2[i-1], c = dp_3[i+1] a=dp1[i],b=dp2[i1],c=dp3[i+1] and d d d is a Constant-Element;
. . Now, given you another matrix- T [ d , e , f ] T[d, e, f] T[d,e,f] whose DP-Time is j j j, then we would know that, d = d p 1 [ j ] , e = d p 2 [ j − 1 ] , f = d p 3 [ j + 1 ] d = dp_1[j], e = dp_2[j - 1], f = dp_3[j + 1] d=dp1[j],e=dp2[j1],f=dp3[j+1]$;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值