@HDU @HDU6395 暑假多校训练营第七场:1010-Sequence (矩阵快速幂+分块)

版权声明:岂曰无衣,与子同袍 https://blog.csdn.net/sizaif/article/details/81700345

Let us define a sequence as below
 


求 Fn (mod 1e9+7)

[思路]

如果没有  [P/N] 的话, 直接上快速幂就可以了,但是 有[P/N] 是变化的不是常数, 

如果能转化成常数运算,  就非常简单了,

我们可以发现, [P/N] 在 某一段内 值是固定的,  所以就可以 分段 快速幂, 例如

P = 10;    10/4 ,10/5 都是2,   10/6-10/10 都是1 .  就可 找到 右端点,  然后进行快速幂...

构造矩阵:

Fn:    D C P/i    Fn-1

Fn-1: 1  0   0    Fn-2

P/i:    0  0   1     P/i-1

[代码]

#include <iostream>
#include <bits/stdc++.h>

#define rep(i,a,n) for(int i =a;i<=n;i++)
#define per(i,a,n) for(int i =n;i>=a;i--)

typedef long long ll;

const int maxn = 1e5+10;
const int mod =1e9+7;
const int MAXN = 3;
const int N = 5;
using namespace std;

ll A,B,C,D,P,n;
ll f[5];

struct Matrix{
    ll arr[N][N];
    void init()
    {
        memset(arr,0,sizeof(arr));
        for(int i = 0;i < MAXN;i++)
            arr[i][i]=1;
    }
    void iinit()
    {
        memset(arr,0,sizeof(arr));
        arr[0][0] = D;arr[0][1] = C;
        arr[2][2] = 1;arr[1][0] = 1;
    }
};
Matrix mul(Matrix X,Matrix Y)
{
    Matrix ans;
    for(int i = 0;i<MAXN;i++)
        for(int j=0;j<MAXN;j++){
            ans.arr[i][j]=0;
            for(int k =0;k<MAXN;k++){
                ans.arr[i][j] += X.arr[i][k]*Y.arr[k][j];
                ans.arr[i][j]%=mod;
            }
        }
    return ans;
}
Matrix Q_pow(Matrix B,ll n)
{
    Matrix ans;
    ans.init();
    while(n)
    {
        if(n&1)
        {
            ans = mul(ans,B);
        }
        B = mul(B,B);
        n>>=1;
    }
    return ans;
}


int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d %d %d %d %d %d",&A,&B,&C,&D,&P,&n);
        Matrix res;
        res.iinit();
        if(n<=2)
        {
            if(n==1)
            {
                printf("%d\n",A%mod);
            }
            else
                printf("%d\n",B%mod);
            continue;
        }
        else
        {
            f[1] = A,f[2] = B;
            ll f1 = f[2], f2 = f[1];
            for(int i = 3,gx; i<= n; i = gx+1)
            {
                gx = P/i ? min(P/(P/i),n):n;
                res.arr[0][2] = P/i;
                Matrix Ans = Q_pow(res,gx-i+1);
                f[3] = ( f1*Ans.arr[0][0]%mod + f2*Ans.arr[0][1]%mod + Ans.arr[0][2]%mod )%mod;
                f[4] = ( f1*Ans.arr[1][0]%mod + f2*Ans.arr[1][1]%mod + Ans.arr[1][2]%mod )%mod;
                f1 = f[3];
                f2 = f[4];
            }
            printf("%d\n",f1);
        }

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sizaif/article/details/81700345