hdu 5667 Sequence 矩阵快速幂

题目链接:hdu 5667 Sequence

思路:因为fn均为a的幂,所以:

这样我们就可以利用快速幂来计算了

注意:

  1. 矩阵要定义为long long,不仅仅因为会爆,还会无限超时
  2. 要对a%p==0特判,以为可能出现指数%(p-1)==0的情况,那么在快速幂的时候返回的结果就是1而不是0了
/**************************************************************
    Problem:hdu 5667
    User: youmi
    Language: C++
    Result: Accepted
    Time:0MS
    Memory:1580K
****************************************************************/
//#pragma comment(linker, "/STACK:1024000000,1024000000")
//#include<bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <stack>
#include <set>
#include <sstream>
#include <cmath>
#include <queue>
#include <deque>
#include <string>
#include <vector>
#define zeros(a) memset(a,0,sizeof(a))
#define ones(a) memset(a,-1,sizeof(a))
#define sc(a) scanf("%d",&a)
#define sc2(a,b) scanf("%d%d",&a,&b)
#define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define scs(a) scanf("%s",a)
#define sclld(a) scanf("%I64d",&a)
#define pt(a) printf("%d
",a)
#define ptlld(a) printf("%I64d
",a)
#define rep0(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define rep_1(i,n) for(int i=n;i>=1;i--)
#define rep_0(i,n) for(int i=n-1;i>=0;i--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
#define lson (step<<1)
#define rson (lson+1)
#define esp 1e-6
#define oo 0x3fffffff
#define TEST cout<<"*************************"<<endl

using namespace std;
typedef long long ll;
ll n,modp,modq;
const int maxn=3;
struct matrix
{
    ll mat[maxn][maxn];
    matrix operator*(const matrix & rhs)const
    {
        matrix ans;
        rep0(i,maxn)
            rep0(j,maxn)
            ans.mat[i][j]=0;
        rep0(i,maxn)
            rep0(j,maxn)
                rep0(k,maxn)
                ans.mat[i][j]=(ans.mat[i][j]+mat[i][k]*rhs.mat[k][j])%modp;
        return ans;
    }
    matrix operator^(ll k)const
    {
        matrix rhs=*this;
        matrix res;
        rep0(i,maxn)
            rep0(j,maxn)
                res.mat[i][j]=(i==j);
        while(k)
        {
            if(k&1)
                res=res*rhs;
            rhs=rhs*rhs;
            k>>=1;
        }
        return res;
    }
}x;
ll q_pow(ll a,ll b)
{
    ll res=1;
    while(b)//a%p==0,当b为0是返回的结果是1而不是0 !!!
    {
        if(b&1)
            res=res*a%modq;
        b>>=1;
        a=a*a%modq;
    }
    return res;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    int T_T;
    scanf("%d",&T_T);
    for(int kase=1;kase<=T_T;kase++)
    {
        ll a,b,c;
        scanf("%I64d%I64d%I64d%I64d%I64d",&n,&a,&b,&c,&modq);
        modp=modq-1;
        if(n==1)
        {
            printf("1
");
            continue;
        }
        else if(n==2)
        {
            printf("%I64d
",q_pow(a,b));
            continue;
        }
        if(a%modq==0)
        {
            printf("0
");
            continue;
        }
        x.mat[0][0]=c%modp,x.mat[0][1]=1,x.mat[0][2]=b%modp;
        x.mat[1][0]=1,x.mat[1][1]=0,x.mat[1][2]=0;
        x.mat[2][0]=0,x.mat[2][1]=0,x.mat[2][2]=1;
        x=x^(n-2);
        ll temp=((x.mat[0][0]*b)%modp+x.mat[0][2])%modp;
        temp=q_pow(a,temp);
        printf("%I64d
",temp);
    }
}
不为失败找借口,只为成功找方法
原文地址:https://www.cnblogs.com/youmi/p/5451355.html