证明见:传送门 。之后就是矩阵快速幂了
#include<stdio.h>
#include<string.h>
#include<math.h>
const int N=2;
typedef long long LL;
struct Matrix{
int a[N][N];
void init(){
memset(a,0,sizeof a);
}
void unit(){
memset(a,0,sizeof a);
for(int i=0;i<N;i++)
a[i][i]=1;
}
};
int a,b,n,m;
Matrix multiply(Matrix x,Matrix y){//矩阵乘
Matrix rst;
rst.init();
for(int i=0;i<N;i++){
for(int j=0;j<N;j++)
for(int k=0;k<N;k++){
rst.a[i][j]+=x.a[i][k]*y.a[k][j];
rst.a[i][j]%=m;
}
}
return rst;
}
Matrix _pow(Matrix a,int p){//快速幂
Matrix rst;
rst.unit();
while(p){
if(p&1)
rst=multiply(rst,a);
a=multiply(a,a);
p>>=1;
}
return rst;
}
void solve(int n){
Matrix A,B,C;
A.a[0][0]=(2*a) % m;
A.a[0][1]=((b-a*a)%m+m)%m;
A.a[1][0]=1;
A.a[1][1]=0;
B=_pow(A,n);
C.a[0][0]=(2*(a*a%m)%m+2*b)%m;
C.a[1][0]=(2*a)%m;
C.a[0][1]=C.a[1][1]=0;
if(n==0)
printf("%d\n",C.a[0][0]%m);
else{
A=multiply(B,C);
printf("%d\n",A.a[0][0]%m);
}
}
int main(){
while(~scanf("%d%d%d%d",&a,&b,&n,&m)){
if(n==1)
printf("%d\n", (int)ceil((a*1.0+sqrt(b*1.0))*1.0)%m);
else
solve(n-2);
}
return 0;
}