HDU多校 6395 Sequence (矩阵快速幂)(模板)

  • 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6395
  • 思路:[p/n]的值是一段一段的, 每段的区间和p的因数有关,每个区间内是相等的。利用矩阵相乘的性质把p/n的值放入矩阵的幂运算中。再一段一段算即可。
  • 坑点:当n大于p时,p的因数都小于n,所以要在p的因数序列末尾加入一个n,补充计算。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <math.h>
#define pi acos(-1.0 )
#define fastio ios_base::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;       // 不能加负号!!!
const LL LL_INF = 0x3f3f3f3f3f3f3f3f;//4e18 ~= 2^62
const int maxn =100000 + 10;
const LL mod = 1e9+7;

vector<LL> V;

typedef struct MATRIX
{
    LL mat[5][5];
}MATRIX;

inline MATRIX mul(MATRIX a,MATRIX b,int n)
{
    MATRIX c;
    memset(c.mat,0,sizeof(c.mat));
    for(int k=0;k<n;k++)
        for(int i=0;i<n;i++)
            if(a.mat[i][k])
                for(int j=0;j<n;j++)
                    if(b.mat[k][j])
                    {
                        c.mat[i][j]+=a.mat[i][k]*b.mat[k][j]%mod;
                        c.mat[i][j]%=mod;
                    }
    return c;
}
inline MATRIX pow(MATRIX a,int N,int n)
{
    MATRIX E;
    memset(E.mat,0,sizeof(E.mat));
    for(int i=0;i<n;i++) E.mat[i][i]=1;
    while(N>0)
    {
        if(N & 1)
            E=mul(E,a,n);
        N>>=1;
        a=mul(a,a,n);
    }
    return E;
}

int main()
{
    MATRIX A, B;
    int T; scanf("%d", &T);
    while(T--){
        memset(A.mat,0,sizeof(A.mat));
        memset(B.mat,0,sizeof(B.mat));
        LL a, b, c, d, p, n;
        scanf("%lld%lld%lld%lld%lld%lld", &a, &b, &c, &d, &p, &n);
        if(n<=2){
            if(n==1) cout<<a<<endl;
            else cout<<b<<endl;
            continue;

        }
        LL sq = sqrt(p);
        V.clear();
        bool f = true;
        for(LL i=1; i*i<=p; i++){
            V.push_back(i);
            if(i == n) f = false;
        }
        for(LL i=(int)V.size()-1;i>=0;i--){
            if(p/V[i] != V[i]) V.push_back(p/V[i]);
            if(p/V[i] == n) f = false;
        }
        if(f) V.push_back(n);

        B.mat[0][0] = b;
        B.mat[1][0] = a;
        B.mat[2][0] = 1;
        bool flag = true;
        int i;
        for(i=1; i<V.size(); i++){
            //cout<<"____________________________________"<<endl;
            if(V[i]<3) continue;
            A.mat[0][0] = d;
            A.mat[0][1] = c;
            A.mat[0][2] = p/V[i];
            A.mat[1][0] = 1;
            A.mat[1][1] = 0;
            A.mat[1][2] = 0;
            A.mat[2][0] = 0;
            A.mat[2][1] = 0;
            A.mat[2][2] = 1;
            if(V[i] > n) break;
            if(flag) A = pow(A, V[i]-2, 3),flag = false;
            else A = pow(A,V[i] - V[i-1], 3);
//            for(int j=0; j<=2; j++){
//                 printf("A: %lld %lld %lld\n", A[j][0], A[j][1], A[j][2]);
//            }
//            printf("B: %lld %lld %lld\n", B[0][0], B[1][0], B[2][0]);

            B = mul(A, B, 3);
            B.mat[2][0] = 1;
        }
        if(V[i-1] < n){
            if(flag) A = pow(A, n-2, 3),flag = false;
            else A = pow(A,n - V[i-1], 3);
            B = mul(A, B, 3);
        }

//        cout<<".........."<<(int) V.size() - 2<<endl;
        printf("%lld\n", B.mat[0][0]);
    }

}

猜你喜欢

转载自blog.csdn.net/qq_37352710/article/details/81666874
今日推荐