http://acm.hdu.edu.cn/showproblem.php?pid=5667
Sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2706 Accepted Submission(s): 904
Problem Description
Holion August will eat every thing he has found.
Now there are many foods,but he does not want to eat all of them at once,so he find a sequence.
He gives you 5 numbers n,a,b,c,p,and he will eat fn foods.But there are only p foods,so you should tell him fn mod p.
Input
The first line has a number,T,means testcase.
Each testcase has 5 numbers,including n,a,b,c,p in a line.
1≤T≤10,1≤n≤1018,1≤a,b,c≤109,p is a prime number,and p≤109+7.
Output
Output one number for each case,which is fn mod p.
Sample Input
1
5 3 3 3 233
Sample Output
190
Source
思路
题目大意:给你一个这样的公式, 然后求fn 对p求余,给出n,a,b,c,p
题目思路:首先我们可以很轻松的构造出这样一个东西,这个fn一定是a的幂次,所以我们稍微推一下可知,对于fn,令他的幂系数为f(n),则f(n) = c*f(n-1)+f(n-2)+b,具体推导见下图:
然后构造一下矩阵去计算这个系数,但是需要注意的是,这里算矩阵的时候不能够对MOD求余,而是对MOD-1求余,因为由费马小定理可知%mod,所以我们矩阵快速幂的系数是对p-1求余,然后还需要去注意的一点是当a%p == 0时,需要特殊处理,比如3 4 3 2 2这组数据,不特殊处理会输出1,但是实际上应该输出0,手动模拟一下就好了:
构造矩阵如图:
AC Code
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll nmax=3;
ll MOD;
#define mod(x) ((x)%MOD)
struct mat{
ll m[nmax][nmax];
}unit;
//A*B^(n-2)=C //C矩阵的首项即为f(n)
mat operator *(mat a,mat b){
mat ret;
ll x;
for(ll i=0;i<nmax;i++){//3*3
for(int j=0;j<nmax;j++){
x=0;
for(ll k=0;k<nmax;k++){
x+=mod((ll)a.m[i][k]*b.m[k][j]);
}
ret.m[i][j]=mod(x);
}
}
return ret;
}
void init_unit(){
for(ll i=0;i<nmax;i++){
unit.m[i][i]=1;
}
return;
}
mat pow_mat(mat a,ll n){//求矩阵a的n次幂
mat ret=unit;
while(n){
if(n&1) ret=ret*a;
a=a*a;
n>>=1;
}
return ret;
}
ll quick_pow(ll a,ll n){//求数a的n次幂
ll ans=1;
while(n){
if(n&1) ans=(ans*a)%MOD;
a=(a*a)%MOD;
n>>=1;
}
return ans;
}
int main(int argc, char** argv) {
ll t;
ll n,A,B,C,P,ans;
init_unit();
scanf("%lld",&t);
while(t--){
scanf("%lld %lld %lld %lld %lld",&n,&A,&B,&C,&P);
MOD=P;
if(n==1) printf("1\n");
else if(n==2) printf("%d\n",quick_pow(A,B));//A^B
else{
if(A%P == 0) {printf("0\n");continue;}
mat a,b;
b.m[0][0]=C;b.m[0][1]=1;b.m[0][2]=0;
b.m[1][0]=1;b.m[1][1]=0;b.m[1][2]=0;
b.m[2][0]=B;b.m[2][1]=0;b.m[2][2]=1;
a.m[0][0]=B;a.m[0][1]=0;a.m[0][2]=1;
MOD--;
b=pow_mat(b,n-2);
a=a*b;
MOD++;
ans=quick_pow(A,a.m[0][0]);//A^F(n)
printf("%lld\n",ans);
}
}
return 0;
}