题目描述
Pty一觉醒来,发现自己竟然陷身于一个巨大的金字塔中。在漆黑一片的通道里,四周闪烁着诡异的绿色,像是许多怪物的眼。阴森的冷风阵阵吹来,像是苏醒的法老抚摸着你的背。Pty不禁打了个寒颤,他必须逃出这里!!经过一番摸索,pty终于找到了金字塔的出口,可是出口却已经被锁住了。拂下锁上的灰尘,pty依稀辨别出锁上的古埃及文字。上面竟然记录着一道智力题!题目经过翻译如下:
有若干个递推序列,每个序列可以表示成如下形式:
现在需要快速求出an mod p的值(保证P是素数)。
这个问题显然已经超出了pty的能力范围,你能帮帮他吗?
递推式
设
an=An∗a0+BnCn∗a0+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);
}
}