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.
fn=⎧⎩⎨⎪⎪1,ab,abfcn−1fn−2,n=1n=2otherwise
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.
Now there are many foods,but he does not want to eat all of them at once,so he find a sequence.
fn=⎧⎩⎨⎪⎪1,ab,abfcn−1fn−2,n=1n=2otherwise
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 .
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
solution:
对于递推式,取以a为底的对数,得到f[n]=c*f[n-1]+f[n-2]+b;此时用矩阵快速幂即可。
tips:
因为p为素数,且模的位置在指数,因此模p-1即可。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 5;
typedef long long ll;
struct Mat{
int row, col;
ll mat[maxn][maxn];
};
Mat mat_mul(Mat A, Mat B, ll p)
{
Mat ans;
ans.row = A.row;
ans.col = B.col;
memset(ans.mat, 0, sizeof(ans.mat));
for (int i = 0; i < A.row; i++)
for (int j = 0; j < A.col; j++)
if (A.mat[i][j])
for (int k = 0; k < B.col; k++)
{
ans.mat[i][k] += A.mat[i][j] * B.mat[j][k];
ans.mat[i][k] %= p;
}
return ans;
}
Mat mat_pow(Mat A,ll x,ll p)
{
Mat C;
C.col = A.row;
C.row = A.col;
for (int i = 0; i < C.row; i++)
for (int j = 0; j < C.col; j++)
C.mat[i][j] = (i == j);
while (x)
{
if (x & 1)C = mat_mul(C, A, p);
A = mat_mul(A, A, p);
x >>= 1;
}
return C;
}
ll pow(ll x, ll y, ll p)
{
ll ans = 1;
while (y)
{
if (y & 1)ans = (ans*x) % p;
x = (x*x) % p;
y >>= 1;
}
return ans%p;
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
ll n, a, b, c, p;
scanf("%I64d%I64d%I64d%I64d%I64d", &n, &a, &b, &c, &p);
Mat A, B;
A.row = A.col = 3;
A.mat[0][0] = c; A.mat[0][1] = 1; A.mat[0][2] = 1;
A.mat[1][0] = 1; A.mat[1][1] = 0; A.mat[1][2] = 0;
A.mat[2][0] =0; A.mat[2][1] = 0; A.mat[2][2] = 1;
if (n == 1)printf("1\n");
else if (n == 2)printf("%I64d\n", pow(a, b, p));
else {
B = mat_pow(A,n - 2,p-1);
ll ans = B.mat[0][0] * b + B.mat[0][2]*b;
printf("%I64d\n", pow(a, ans, p));
}
}
}