hdu 5667 Sequence(矩阵快速幂)

来源:互联网 发布:大富翁数据 编辑:程序博客网 时间:2024/06/05 13:34
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,abfcn1fn2,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.

    1T10,1n1018,1a,b,c109,p is a prime number,and p109+7.
 

Output
    Output one number for each case,which is fn mod p.
 

Sample Input
15 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));        }    }}


0 0