此题注意一点就是b>(a-1)^2,b<a^a,所以0<a-sqrt(b)<1,而(a+sqrt(b))^n+(a-sqrt(b))^b为整数,所以题中表达式就等于(a+sqrt(b))^n+(a-sqrt(b))^b。所以应用数列里的特征方程得
b[n]-2*a*b[n-1]+(a*a-b)b[n-2]=0,然后可以转化成矩阵快速幂来求解。下面是源代码。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
long long m;
long long kuai(long long a,long long b,int n)
{
long long x1,y1,x2,y2,s1,s2,s3,s4,a1,b1,a2,b2,k,s;
a1=1;
b1=0;
a2=0;
b2=1;
k=n-2;
x1=2*a%m;
y1=(b%m-a*a)%m+m;
y1%=m;
x2=1;
y2=0;
while(k>0)
{
if(k&1)
{
s=a1;
a1=(a1*x1+b1*x2)%m;
b1=s*y1%m+b1*y2%m;
b1%=m;
s=a2;
a2=a2*x1+b2*x2;
a2%=m;
b2=s*y1+b2*y2;
b2%=m;
}
s1=x1;
s2=y1;
s3=x2;
s4=y2;
x1=s1*s1%m+s2*s3%m;
x1=x1%m;
y1=s1*s2%m+s2*s4%m;
y1%=m;
x2=s3*s1%m+s4*s3%m;
x2%=m;
y2=s2*s3%m+s4*s4%m;
y2%=m;
k>>=1;
}
return (((2*a*a%m+2*(b%m))%m*a1+2*a%m*(b1)%m)%m+m)%m;
}
int main()
{
long long a,b,n;
while(cin>>a>>b>>n>>m)
{
if(n==1)
{
printf("%lld\n",2*a%m);
continue;
}
if(n==2)
{
printf("%lld\n",(2*a%m*a%m+2*(b%m))%m);
continue;
}
printf("%lld\n",kuai(a,b,n));
}
return 0;
}