寺庙逃脱

题目描述

Pty一觉醒来,发现自己竟然陷身于一个巨大的金字塔中。在漆黑一片的通道里,四周闪烁着诡异的绿色,像是许多怪物的眼。阴森的冷风阵阵吹来,像是苏醒的法老抚摸着你的背。Pty不禁打了个寒颤,他必须逃出这里!!经过一番摸索,pty终于找到了金字塔的出口,可是出口却已经被锁住了。拂下锁上的灰尘,pty依稀辨别出锁上的古埃及文字。上面竟然记录着一道智力题!题目经过翻译如下:

有若干个递推序列,每个序列可以表示成如下形式:
这里写图片描述
现在需要快速求出an mod p的值(保证P是素数)。

这个问题显然已经超出了pty的能力范围,你能帮帮他吗?

递推式

an=Ana0+BnCna0+Dn
然后发现A、B、C、D有递推式。
矩阵乘法优化即可。

#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
int i,j,k,l,t,m,mo,a0,ca,top,num;
ll n;
int s[100];
struct dong{
    int a[3][3];
    friend dong operator *(dong a,dong b){
        int i,j,k;
        dong c;
        fo(i,1,2)
            fo(j,1,2)
                c.a[i][j]=0;
        fo(k,1,2)
            fo(i,1,2)
                fo(j,1,2)
                    c.a[i][j]=(c.a[i][j]+(ll)a.a[i][k]*b.a[k][j]%mo)%mo;
        return c;
    }
};
dong ans,tmp;
int read(){
    ll x=0,f=1;
    char ch=getchar();
    while (ch<'0'||ch>'9'){
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0'&&ch<='9'){
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int qsm(int x,int y){
    if (!y) return 1;
    int t=qsm(x,y/2);
    t=(ll)t*t%mo;
    if (y%2) t=(ll)t*x%mo;
    return t;
}
int main(){
    ca=read();
    while (ca--){
        a0=read();tmp.a[1][1]=read();tmp.a[1][2]=read();tmp.a[2][1]=read();tmp.a[2][2]=read();n=read();mo=read();
        if (!n){
            printf("%d\n",a0);
            continue;
        }
        top=0;
        while (n){
            s[++top]=n%2;
            n/=2;
        }
        ans.a[1][1]=ans.a[2][2]=1;
        ans.a[1][2]=ans.a[2][1]=0;
        while (top){
            ans=ans*ans;
            if (s[top]) ans=ans*tmp;
            top--;
        }
        num=((ll)ans.a[1][1]*a0%mo+ans.a[1][2])%mo;
        t=((ll)ans.a[2][1]*a0%mo+ans.a[2][2])%mo;
        num=(ll)num*qsm(t,mo-2)%mo;
        num=(num+mo)%mo;
        printf("%d\n",num);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值