Fast power line matrix optimization dp

\ (T1 \) line up

Description

  

Grab dinner is a part of high school life, and now has a team of length \ (the n-\) , ( Note: Due to keep the distance between people and different situations keeping a distance of different sizes, so the length of the queue does not directly reflect the number of people) . The distance between men and men are known as \ (A \) , the distance between men and women is a b b, the distance between the female is \ (c \) . A male Dafan time \ (D \) , a girl Dafan time \ (E \) , the sum of the queue time required in all cases (ignoring the contribution ranks of the body size of the length), the answer to $ 10 ^ {9} $ modulo +7.

  

Input Format

Line six integer \ (n-\) , \ (A \) , \ (B \) , \ (C \) , \ (D \) , \ (E \) .

Output

An integer line, that is the answer.

Solution

First, it is easy to think of a DP practice, where we construct \ (f \) \ ([i] [0/1] \) array, represents the last person in the case of 0/1, the last person to hit rice of the time and, 0 represents the last one is male, one is female.

Definition of G \ ([I] [0/1] \) Total number represents the last program in the case where a person is in. Hand push the state transition equation:

E.PNG

But we will find that \ (n \) is very large, but \ (A \) , \ (b \) , \ (c \) , is very small, so each time you transfer the required \ (ia \) , \ (ib \) , \ (ic \) it is very close, so you can consider using the scroll array transfer.

But did not make the scroll array optimized for time.

Here we use the transfer matrix multiplication instead, only a configuration \ (4 * max (a, b, c) \) transfer matrix to order.

Let's talk about the detailed structure of the matrix! !

First seen \ (g \) array of (f \) \ transfer array had an impact, so we not just transfer matrix \ (f \) , must also join \ (g \) transfer.

Normally, the initial matrix construct a long way:

A.PNG

However, considering the \ (F \) \ ([I] [0/1] \) and G \ ([I] [0/1] \) of the four to be transferred with the stuff, so each \ (I \) to maintain the value of four, so maintaining four values in each block, it becomes:

B.PNG

Okay, so that you can explain why \ (4 * max (a, b, c) \) order, the order is the length and width of the matrix meaning friends

Then the matrix structure on one goal:

C.PNG

This means that the \ (R & lt \) Release \ (R & lt. 1 + \) , and then against the transfer equation dp configured above a transfer matrix alone.

Shaped like:

D.PNG

After completion of the transfer matrix configuration fast power, quickly get the final answer \ (F [n-] [0] \) + \ (F [n-] [. 1] \)

Details : When the code is implemented because as every one four, so we use \ (<< 2 \) (equivalent to x 4) positions may be quickly i corresponds to each matrix, each block is selected by | (= add operation or operation) to process the code simple.

#include<bits/stdc++.h>
#define ll long long
#define N 150
using namespace std;
const int mod=1e9+7;
ll n;
int a,b,c,d,e,O;
int g[N][2],f[N][2];// f[i][0/1]表示长度为i的队伍最后为男生(0)或女生(1)的答案  g[i][1/0]与f一样,不过是记录到达这个状态的方案数 
struct Matrix{
    int a[N][N];
    Matrix(){memset(a,0,sizeof(a));}
}T,qs,asd;//T为转移矩阵 qs为初始矩阵 
void mul(Matrix &CC,Matrix A,Matrix B)
{
    Matrix C;
    int i,j; 
    for(i=0;i<O;i++)
       for(j=0;j<O;j++)
          C.a[i][j]=0;
          
    for(i=0;i<O;i++)   //两个矩阵的相乘 
    for(j=0;j<O;j++)
    if(A.a[i][j])
    {
        for(int k=0;k<O;k++)
           if(B.a[j][k])
            C.a[i][k]=(1ll*A.a[i][j]*B.a[j][k]+C.a[i][k])%mod;
    }
    CC=C;
}
void Ksm(Matrix &CC,Matrix AA,ll t)  //标准快速幂 
{
    Matrix A,C;
    t--;
    A=C=AA;
    while(t)
    {
        if(t&1)
        {
            mul(C,C,A);
        }
        mul(A,A,A);
        t>>=1;
    }
    CC=C;
}
int main()
{
    int i,j;
    scanf("%lld",&n);
    scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);
    g[0][0]=g[0][1]=1;  //初始化 
    f[0][0]=d,f[0][1]=e;   //初始化
    int o=max(a,max(b,c)); //转移所需的最小的矩阵 
    O=o<<2;//矩阵长宽
    for(i=1;i<o;i++)// 初始化第一个矩阵 
    {
        if(i>=a) (f[i][0]+=f[i-a][0])%mod,(g[i][0]+=g[i-a][0])%mod;
        if(i>=b) (f[i][0]+=f[i-b][1])%mod,(g[i][0]+=g[i-b][1])%mod,(f[i][1]+=f[i-b][0])%mod,(g[i][1]+=g[i-b][0])%mod;
        if(i>=c) (f[i][1]+=f[i-c][1])%mod,(g[i][1]+=g[i-c][1])%mod;
        f[i][0]=(1ll*g[i][0]*d+f[i][0])%mod;
        f[i][1]=(1ll*g[i][1]*e+f[i][1])%mod;
    } 
    //下面开始把我们构造的转移矩阵完善一下 
    for(i=1;i<o;i++)
    {
        for(j=0;j<4;j++)
        T.a[i<<2|j][(i-1)<<2|j]=1; //把矩阵中的1全填了再说 
    }
    T.a[(o-b)<<2][(o-1)<<2|1] = T.a[(o-b)<<2|2][(o-1)<<2|3] = T.a[(o-b)<<2|1][(o-1)<<2] = T.a[(o-b)<<2|3][(o-1)<<2|2] = 1; //把公式中的全部i-b的影响填上1 
    T.a[(o-b)<<2|2][(o-1)<<2|1] = e; T.a[(o-b)<<2|3][(o-1)<<2] = d; //把e和d填上
     //后面也在一个一个填数 
     ++T.a[(o-a)<<2][(o-1)<<2]; ++T.a[(o-a)<<2|2][(o-1)<<2|2];  
     (T.a[(o-a)<<2|2][(o-1)<<2]+=d)%mod;
     ++T.a[(o-c)<<2|1][(o-1)<<2|1]; ++T.a[(o-c)<<2|3][(o-1)<<2|3];
     (T.a[(o-c)<<2|3][(o-1)<<2|1]+=e)%mod;
     
     for(i=0;i<o;i++)  //把之前求出的初始f付给这个初始矩阵 
     {
        qs.a[0][i<<2] = f[i][0];
        qs.a[0][i<<2|1] = f[i][1];
        qs.a[0][i<<2|2] = g[i][0];
        qs.a[0][i<<2|3] = g[i][1];
     } 
     Ksm(T,T,n-o+1); mul(qs,qs,T);  //快速转移 
     printf("%d\n",(qs.a[0][(o-1)<<2]+qs.a[0][(o-1)<<2|1])%mod);  //取最后的答案 
    return 0;
} 

Guess you like

Origin www.cnblogs.com/yzxx/p/11722839.html