Fast power optimization template matrix dp

 Related blog: https://blog.csdn.net/china_xyc/article/details/89819376#commentBox

Matrix multiplication can be optimized on the subject DP, we have the following requirements:

  1. Only adder transfer type, clears, subtraction etc., max and min is not allowed in
  2. Where the transfer coefficient on the first few dp result must be a constant
  3. The number of transitions in general Super Multi
  4. Since the number of times of transfer, generally have a modulus within the range of int

In summary, an example:

dp[i]=a×dp[i−1]+b×dp[i−2]+c×dp[i−3]

Wherein, a, b, c are constants, and the required matrix optimization of the DP, often i 2 ^ 128 or the like, particularly Kichiku particularly large number;
because the optimized matrix multiplication find DP [i] is in O time log (i) is completed.
So, how to achieve matrix multiplication, its principle is Shane?
Matrix multiplication requires two matrices A and B, A is an n × p, B is the size of p × m, below

 

 

For ease of explanation, we give examples of Fibonacci deed.
Fibonacci transfer formula is: dp [i] = dp [ i-1] + dp [i-2].
We then (dp [i], dp [ i-1]) regarded as a 1 × 2 matrix A is
each time multiplied by the matrix A is equivalent to transfer F.:
|. 1. 1 |
| 0. 1 |
the results is: (dp [i] + dp [i-1], dp [i]), which is (dp [i + 1], dp [i])
then once every 8 times required matrix multiplication operations, while the original state transition required only once, so do not see matrix multiplication algorithm on a waste wood it. .
The key is! Matrix multiplication has associativity, hey hey hey, then we can begin to quickly power up! Look at it this way O (n) algorithm optimization has become a simple O (8 × logn) algorithm in n Fried Chicken Fried Chicken big metamorphosis time we can use this optimized.

 

 

Do your own examples  https://www.luogu.org/problem/P5343

Knowledge used: a set of intersected (bitset <N> = and &) linear recursive (DP)   matrix acceleration ( matrix flash power ) (in fact, somewhat like a scroll array)
linear recursive feeling is: f (n) = f (n-1) + f (n-2), and then to know the value f (1), f (2 ) , the introduction of f (3) value, and then has to recursive down, it is to know the value of the foregoing go We know the value of the latter.

 

 

#include <cstdio>
#include <cstring>
#include <iostream>
#include <bitset>
#include <algorithm>
using namespace std;

typedef long long ll;
const int maxn = 105;
const int mod = 1e9+7;
ll n;
int m,x;
bitset<maxn> a,b;
ll g[maxn][maxn],tmp[maxn][maxn],res[maxn][maxn];
ll dp[maxn];

void mult(ll a[][maxn],ll b[][maxn]){
    memset(tmp,0,sizeof(tmp));
    for(int i=1; i<=100; i++){
        for(int j=1; j<=100; j++){
            for(int k=1; k<=100; k++){
                tmp[i][j] = (tmp[i][j] + a[i][k]*b[k][j]%mod)%mod;
            }
        }
    }
    for(int i=1; i<=100; i++){
        for(int j=1; j<=100; j++){
            a[i][j] = tmp[i][j];
        }
    }
}

void qpow(ll a[][maxn],ll N){
    memset(res,0,sizeof(res));
    for(int i=1; i<=100; i++){
        res[i][i] = 1;
    }
    while(N){
        if(N&1) mult(res,a);
        mult(a,a);
        N>>=1;
    }
    for(int i=1; i<=100; i++){
        for(int j=1; j<=100; j++){
            a[i][j] = res[i][j];
        }
    }
}

int main(){
    scanf("%lld%d",&n,&m);
    for(int i=0; i<m; i++){
        scanf("%d",&x);
        a[x] = 1;
    }
    scanf("%d",&m);
    for(int i=0; i<m; i++){
        scanf("%d",&x);
        b[x] = 1;
    }
    a &= b;

    for(int i=1; i<=100; i++){
        if(a[i]) g[1][i]=1;
    }
    for(int i=2; i<=100; i++){
        g[i][i-1] = 1;
    }

    // dp[0] = 1;
    // for(int i=0; i<=100; i++){
    //     for(int j=1; j<=i; j++){
    //         if(a[j]){
    //             dp[i] = (dp[i] + dp[i-j] )%mod;
    //         }
    //     }
    // }
    // if(n<=99) printf("%d\n", dp[n]);
    // else{
    //     qpow( g ,n-99);
    //     ll ans = 0;
    //     for(int i=1; i<=100; i++){
    //         = ANS (ANS + DP [I-100] * G [. 1] [I]% MOD) MOD%;
     //      }
     //      the printf ( "% LLD \ n-", ANS);
     // } 

    // original direct matrix fast power can ah .. since f (1) = 0, then as the first to make a direct 
    qpow (G, N- 0 ); 
    the printf ( " % LLD \ n- " , G [ . 1 ] [ . 1 ]) ; 
}

 

Guess you like

Origin www.cnblogs.com/-Zzz-/p/11483220.html