您的位置:首页 > 产品设计 > UI/UE

hdu 5667 Sequence(矩阵快速幂)

2016-04-20 20:19 609 查看
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.

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


solution:
对于递推式,取以a为底的对数,得到f
=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));
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: