题目
Description
Input
第一行一个整数 T 表示数据组数。
接下来 T 行,每行五个整数 a,b,n,k,p,含义见题目。
Output
对于每组数据,输出一个整数表示答案。
Sample Input
输入样例:
1
0 1 2 2 1000
Sample Output
输出样例:
8
Data Constraint
思路
可以发现题目中的递推式其实就是斐波那契数列。
斐波那契数列在模 p 意义下的循环节是容易计算的。
至于怎么计算,dh大佬推荐了几篇博文:
https://wenku.baidu.com/view/7fc328eb4693daef5ef73d87.html
https://blog.csdn.net/abc13068938939/article/details/53836482
https://www.cnblogs.com/yicongli/p/9800705.html
代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e7+77;
struct M
{
int r,c;
ll a[2][2];
};
ll now_p,A,B;
int L=1e7,cnt,pri[N];
bool bo[N];
void init()
{
for(int i=2; i<=L; i++)
{
if(!bo[i]) pri[++cnt] = i;
for(int j=1; j<=cnt&&i*pri[j]<=cnt; j++)
{
bo[i*pri[j]]=1;
if(i%pri[j]==0) break;
}
}
}
ll mul(ll x,ll y)
{
ll yjy=x*y-(ll)((long double)x*y/now_p+1e-8)*now_p;
return yjy<0?yjy+now_p:yjy;
}
void add(ll &x,ll y)
{
(x+=y)>=now_p?x-=now_p:0;
}
M operator*(M a,M b)
{
M c;
memset(c.a,0,sizeof(c.a));
for(int i=0; i<a.r; i++) for(int k=0; k<b.r; k++) for(int j=0; j<b.c; j++)
add(c.a[i][j],mul(a.a[i][k],b.a[k][j]));
c.r=a.r; c.c=b.c;
return c;
}
ll calc(ll n)
{
M yjy,c;
yjy.a[1][0]=yjy.a[1][1]=0;
yjy.a[0][0]=A%now_p; yjy.a[0][1]=B%now_p;
yjy.r=1; yjy.c=2;
c.a[0][0]=0; c.a[0][1]=now_p - 1;
c.a[1][0]=1; c.a[1][1]=3;
c.r=c.c=2;
while(n)
{
if(n&1) yjy=yjy*c;
n>>=1;
c=c*c;
}
return yjy.a[0][0];
}
ll get_g(ll p)
{
return p==2?3:p==5?20:p%5==1?p-1:p%5==4?p-1:2*p+2;
}
ll lcm(ll a,ll b)
{
return a/__gcd(a,b)*b;
}
ll find(ll x)
{
ll yjy=1,s=sqrt(x);
for(int i=1; i<=cnt&&pri[i]<=s; i++) if(x%pri[i]==0)
{
int p=pri[i];
ll t=get_g(p);
while(x%p==0)
{
x/=p; t*=p;
}
t/=p;
yjy=lcm(yjy,t);
}
if(x!=1) yjy=lcm(yjy,get_g(x));
return yjy;
}
ll solve(ll n,ll k,ll p)
{
if(!k) return n%p;
ll cir=find(p),nxt=solve(n,k-1,cir);
now_p=p;
ll yjy=calc(nxt);
return yjy;
}
void work()
{
scanf("%d%d",&A,&B);
int n,k,p;
scanf("%d%d%d",&n,&k,&p);
ll ans=solve(n,k,p);
printf("%d\n",ans);
}
int main()
{
freopen("hakugai.in","r",stdin); freopen("hakugai.out","w",stdout);
init();
int T;
scanf("%d",&T);
while(T--) work();
}