HDU 5667 Sequence(矩阵快速幂+费马小定理)

本文介绍了一个特定的数学问题解决方法,利用矩阵快速幂和费马小定理来高效计算大数模意义下的数值。通过具体的C++代码实现展示了如何处理大指数的幂运算,并给出了解题思路及代码细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大意:

这里写图片描述

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.

思路:矩阵快速幂一定可以,那么a的指数很大怎么处理呢那么用费马小定理a^(p-1)%p=1;a^(m%(p-1)) %p=1 ; 最后注意 a%p==0的情况。

//|G(n)  |  |c 1 b|  |G(n-1)|  
//|G(n-1)|= |1 0 0|* |G(n-2)|  
//|1     |  |0 0 1|  |1     |  
#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<stack>
#include<iostream>
#include<cstring>
#include<algorithm>
#define LL int
#define inf 0x3f3f3f3f
#define eps 1e-8
#include<vector>
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1

using namespace std;
__int64 mod ,p;

struct node{
    __int64 r[15][15];
}q;

void matrix_pow(node &a,node &b){
    int i,j,k;
    node t;
    for(i= 0;i <3;++ i){
        for(j = 0;j < 3;++ j){
            t.r[i][j]  = 0;
        }
    }
    for(k = 0;k < 3;++ k){
        for(i =0 ;i < 3;i++){
            for(j = 0;j < 3;++ j){
                t.r[i][j] = (t.r[i][j]+a.r[i][k]*b.r[k][j])%mod;
            }
        }
    }
    a = t;
}

void so(node &q,__int64 m){

    __int64 i,j,k;
    node tmp;
    for(i= 0;i <3;++ i){
        for(j = 0;j < 3;++ j){
            tmp.r[i][j]  = 0;
        }
    }
    for(i=0;i<3;++i)
        tmp.r[i][i]=1;

    while(m){
        if(m&1){
           matrix_pow(tmp,q);
        }
        matrix_pow(q,q);
        m =m >> 1;
    }
   q = tmp;
}
__int64 qick(__int64 x,__int64 y){
    x = x%p;
    __int64 ba  = x,r = 1;
    while(y){
        if(y&1)
            r = (r*ba) % p;
        ba  = (ba * ba) % p;
        y >>= 1;
    }
    return r;
}
int main(){
    __int64 k,i,j,n,a,b,c;
    int cla;
    scanf("%d",&cla);
    while(cla--){
        scanf("%I64d %I64d %I64d %I64d %I64d",&n,&a,&b,&c,&p);

        if(n == 1){
            printf("1\n");continue;
        }
        else if(n==2){
            printf("%I64d\n",qick(a,b));continue;
        }

        else if(a%p==0){
            puts("0");continue;
        }

        mod = p - 1;
        memset(q.r,0,sizeof(q.r));
        q.r[0][0] = c,q.r[0][2]=b;
        q.r[0][1] = q.r[1][0] = q.r[2][2] = 1;
        so(q,n-2);

        __int64 ans  =0;

        ans = (ans + b*q.r[0][0])%mod;
        ans = (ans + q.r[0][2])%mod;

        printf("%I64d\n",qick(a,ans));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值