(矩阵快速幂)HDU5667

注意n==1或n==2时最好特判一下。


观察递推式我们可以发现,所有的f_ifi都是aa的幂次,所以我们可以对f_ifi取一个以aa为底的loglog,即g_i=log_a\ f_igi=loga fi

那么递推式变成g_i=b+c*g_{i-1}+g_{i-2}gi=b+cgi1+gi2,这个式子可以矩阵乘法


但要注意a^b%c!=a^(b%c)%c,而是a^b%c=a^(b%phi(c))%c;

由于c为质数,所以phi(c)==c-1;


#include<iostream>
#include<queue>
using namespace std;
typedef long long ll;
typedef vector<ll> vec;
typedef vector<vec> mat;
ll a,b,c,n,p;
mat mul(mat a,mat b)
{
if (a[0].size()!=b.size())
swap(a,b);
int len1=a.size(),len2=b[0].size(),len3=b.size();
mat c(len3,vec(len3));
for (int i=0;i<len1;i++)
for (int j=0;j<len2;j++)
for (int k=0;k<len3;k++)
c[i][j]=(c[i][j]+a[i][k]*b[k][j])%(p-1);
return c;
}
mat mpow(mat a,ll n)
{
int len=a.size();
mat b(len,vec(len));
for (int i=0;i<len;i++)
b[i][i]=1;
while(n)
{
if (n&1)
b=mul(b,a);
n>>=1;
a=mul(a,a);
}
return b;
}
ll pow(ll a,ll n)
{
ll ans=1;
while(n)
{
if (n&1)
ans=(ans*a)%p;
n>>=1;
a=(a*a)%p;
}
return ans;
}
mat ma(1,vec(3)),mb(3,vec(3)),mc;
int main()
{
ll t;
cin>>t;
while(t--)
{
cin>>n>>a>>b>>c>>p;
ma[0][1]=ma[0][2]=1;
mb[0][1]=mb[1][0]=mb[2][1]=mb[2][2]=1;
mb[1][1]=c;
mc=mpow(mb,n-1);
mc=mul(ma,mc);
a=pow(a,b);
a=pow(a,mc[0][0]);
cout<<a<<endl;
}
}#include<iostream>

#include<queue>
using namespace std;
typedef long long ll;
typedef vector<ll> vec;
typedef vector<vec> mat;
ll a,b,c,n,p;
mat mul(mat a,mat b)
{
    if (a[0].size()!=b.size())
    swap(a,b);
    int len1=a.size(),len2=b[0].size(),len3=b.size();
    mat c(len3,vec(len3));
    for (int i=0;i<len1;i++)
    for (int j=0;j<len2;j++)
    for (int k=0;k<len3;k++)
    c[i][j]=(c[i][j]+a[i][k]*b[k][j])%(p-1);
    return c;
}
mat mpow(mat a,ll n)
{
    int len=a.size();
    mat b(len,vec(len));
    for (int i=0;i<len;i++)
    b[i][i]=1;
    while(n)
    {
        if (n&1)
        b=mul(b,a);
        n>>=1;
        a=mul(a,a);
    }
    return b;
}
ll pow(ll a,ll n)
{
    ll ans=1;
    while(n)
    {
        if (n&1)
        ans=(ans*a)%p;
        n>>=1;
        a=(a*a)%p;
    }
    return ans;
}
mat ma(1,vec(3)),mb(3,vec(3)),mc;
int main()
{
ll t;
    cin>>t;
    while(t--)
    {
        cin>>n>>a>>b>>c>>p;
        ma[0][1]=ma[0][2]=1;
   mb[0][1]=mb[1][0]=mb[2][1]=mb[2][2]=1;
        mb[1][1]=c;
        mc=mpow(mb,n-1);
        mc=mul(ma,mc);
        a=pow(a,b);
        a=pow(a,mc[0][0]);
        cout<<a<<endl;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值