寺庙逃脱

来源:互联网 发布:windows 串口编程 编辑:程序博客网 时间:2024/05/02 20:37

题目描述

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);    }}
0 0