思路:
形如f(n)=af(n-1)+bf(n-2)的数列就叫做广义斐波那契数列。
设g(x)为mo=x时的f(n)的循环节,即f(n)f(n%g(x)) (mod x),
则g(x)是一个积性函数。
ps:x不是质数时的结论是下午做题时的猜想,不保证正确性。可以过这个题,但是万一是水过的呢,之后还会再跑程序验证下。
代码:
#include<cstdio>
#include<cstring>
typedef long long ll;
const int N=1000000+10;
struct Node{
int r,c;
ll jz[3][3];
Node(){
memset(jz,0,sizeof(jz));
}
};
ll x0,x1,a,b,n,md,mmd;
char s[N];
int pn,pri[100000+10];
void init(){
ll lim;
for(int i=2;i<=100000;i++){
if(!pri[i]) pri[pn++]=i;
for(int j=0;j<pn;j++){
lim=1ll*i*pri[j];
if(lim>100000) break;
pri[lim]=1;
if(i%pri[j]==0) break;
}
}
}
ll solve(ll x){
ll ans1=1,ans2=1,xx=x;
for(int i=0;i<pn;i++){
if(1ll*pri[i]*pri[i]>x) break;
if(x%pri[i]==0){
ans1*=(pri[i]-1)*(pri[i]+1);
ans2*=pri[i];
while(x%pri[i]==0) x/=pri[i];
}
}
if(x>1){
ans1*=(x-1)*(x+1);
ans2*=x;
}
return xx/ans2*ans1;
}
ll mul(ll x,ll y,ll z){
x%=z;
y%=z;
ll ans=0;
while(y){
if(y&1){
ans+=x;
if(ans>=z) ans-=z;
}
x<<=1;
if(x>=z) x-=z;
y>>=1;
}
return ans;
}
Node Nmul(Node x,Node y,ll z){
Node ans;
ans.r=x.r;
ans.c=y.c;
for(int i=0;i<x.r;i++)
for(int j=0;j<y.c;j++)
for(int k=0;k<x.c;k++){
ans.jz[i][j]+=mul(x.jz[i][k],y.jz[k][j],z)%z;
if(ans.jz[i][j]>=z) ans.jz[i][j]%=z;
}
return ans;
}
Node Npow(Node x,ll y,ll z){
Node ans;
ans.r=x.r;
ans.c=x.c;
for(int i=0;i<ans.c;i++) ans.jz[i][i]=1;
while(y){
if(y&1) ans=Nmul(ans,x,z);
x=Nmul(x,x,z);
y>>=1;
}
return ans;
}
int main(){
init();
while(~scanf("%lld%lld%lld%lld",&x0,&x1,&a,&b)){
scanf("%s%lld",s,&md);
mmd=solve(md);
n=0;
int lens=strlen(s);
for(int i=0;i<lens;i++){
n=mul(n,10,mmd)+s[i]-'0';
if(n>=mmd) n-=mmd;
}
Node A,T;
A.r=2;
A.c=1;
A.jz[0][0]=x1;
A.jz[1][0]=x0;
T.r=2;
T.c=2;
T.jz[0][0]=a;
T.jz[0][1]=b;
T.jz[1][0]=1;
if(n>1){
T=Npow(T,n-1,md);
A=Nmul(T,A,md);
}
printf("%lld\n",A.jz[0][0]);
}
return 0;
}