HDU 6395 矩阵快速幂+分块加速

题目链接

题意:

给定A,B,C,D,P,n求表达式的第n项(mod1e9+7):

F1 = A

F2 = B

Fn = C*Fn-2+D*Fn-1+P/n

思路:

首先如果P/n是一个定值比如说X时,这题就是一个简单的矩阵快速幂根据递推公式可以快速得到矩阵

| D C 1 |

| 1 0 0  |

| 0 0 1  |

但是现在有一个问题P/n是会变化的,而矩阵快速幂又只能在X相等情况下才可以使用,于是思路转向对于P/n相等的那些块采用整块进行矩阵快速幂处理,就是分块加速(分块加速的结论就是对于P来说在区间[i,P/(P/i)]内P/i的计算结果是相同的)

C++代码:

#include<bits/stdc++.h>
using namespace std;
const int mod = 1e9+7;

int Min( int a , int b ){ return a<b?a:b; }

struct Matrix
{
    int m[3][3];
    Matrix(){ memset( m , 0 , sizeof(m) ); }
};

Matrix Mult( Matrix A , Matrix B )
{
    Matrix E;
    for ( int i=0 ; i<3 ; i++ )
        for ( int j=0 ; j<3 ; j++ )
            for ( int k=0 ; k<3 ; k++ )
                E.m[i][j] = ( E.m[i][j]+1LL*A.m[i][k]*B.m[k][j]%mod )%mod;
    return E;
}

Matrix Qpow( Matrix A , int B )
{
    Matrix E;
    E.m[0][0] = 1;
    E.m[1][1] = 1;
    E.m[2][2] = 1;
    while ( B )
    {
        if ( B&1 )
            E = Mult( E , A );
        A = Mult( A , A );
        B = B>>1;
    }
    return E;
}

int main()
{
    for ( int T ; scanf ( "%d" , &T )==1 ; )
    {
        for ( int cas=1 ; cas<=T ; cas++ )
        {
            int A,B,C,D,P,n;
            scanf ( "%d%d%d%d%d%d" , &A , &B , &C , &D , &P , &n );
            if ( n==1 )
                printf ( "%d\n" , A );
            else if ( n==2 )
                printf ( "%d\n" , B );
            else
            {
                for ( int i=3 ; i<=n ; i++ )
                {
                    int X = P/i,r;
                    if ( X==0 ) r = n;
                    else r = P/X;
                    r = Min( r , n );
                    Matrix M;
                    M.m[0][0] = D;
                    M.m[0][1] = C;
                    M.m[0][2] = 1;
                    M.m[1][0] = 1;
                    M.m[2][2] = 1;
                    M = Qpow( M , r-i+1 );
                    int TB = ((1LL*M.m[0][0]*B%mod+1LL*M.m[0][1]*A%mod)%mod+1LL*M.m[0][2]*X%mod)%mod;
                    int TA = ((1LL*M.m[1][0]*B%mod+1LL*M.m[1][1]*A%mod)%mod+1LL*M.m[1][2]*X%mod)%mod;
                    B = TB;
                    A = TA;
                    i = r;
                }
                printf ( "%d\n" , B );
            }
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Game_Acm/article/details/81673909
今日推荐