hdu 5667 Sequence(矩阵快速幂)

42 篇文章 0 订阅
3 篇文章 0 订阅
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
  
  
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));
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值