HDU - 1757 A Simple Math Problem 矩阵快速幂

本文介绍了一种使用矩阵快速幂解决特定递推问题的方法。对于一个复杂的递推公式,当输入值非常大时,直接递推会超时。通过构造特定矩阵,并利用快速幂算法,可以高效地计算出结果并进行取模操作。

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

题目链接:https://vjudge.net/problem/HDU-1757

题意:就是求一个函数f(x)的值,如果x<10,f(x)=x,如果f(x)>=10,给你a0~a9一共10个数,f(x)=a0*f(x-1)+a1*f(x-2)+...+f(x-10)*a9。输出结果要对m取模。(k<=2e9,m<=1e5)。

分析:看起来像是个递推,但是看数据范围十分的大,直接抵退肯定超时,构造矩阵,利用矩阵快速幂求解才能提高效率。具体矩阵构造(在网上找的,因为自己懒得画图):















#include<cstdio>  
#include<cstring>  
#include<iostream>  
#include<algorithm>  
#include<queue>  
using namespace std;  
typedef long long LL;  
const int maxn=10;  
int arr[maxn],f[maxn];  
int k,MOD;  
  
struct Matrix{  
    LL mat[maxn][maxn];  
    Matrix operator*(const Matrix& m) const{//重载乘法运算符  
        Matrix tmp;  
        for(int i=0;i<maxn;i++){  
            for(int j=0;j<maxn;j++){  
                tmp.mat[i][j]=0;  
                for(int k=0;k<maxn;k++){  
                    tmp.mat[i][j]+=mat[i][k]*m.mat[k][j]%MOD;  
                    tmp.mat[i][j]%=MOD;  
                }  
            }  
        }  
        return tmp;  
    }  
};  
  
void init(Matrix& m){ //初始化  
    memset(m.mat , 0 , sizeof(m.mat));  
    for(int i=0;i<maxn;i++)  
        m.mat[0][i]=arr[i];  
    for(int i=0;i<maxn-1;i++)  
        m.mat[i+1][i]=1;  
    for(int i=0;i<maxn;i++)  
        f[i]=i;  
}  
  
LL Pow(Matrix& m){  
    Matrix ans;  
    memset(ans.mat,0,sizeof(ans.mat));  
    for(int i=0;i<maxn;i++)  
        ans.mat[i][i]=1;  
    k-=9;  
    while(k){ //快速幂  
        if(k&1) ans=ans*m;  
        k>>=1;  
        m=m*m;  
    }  
    LL sum=0;  
    for(int i=0;i<maxn;i++){ //计算结果  
        sum+=ans.mat[0][i]*f[maxn-1-i]%MOD;  
        sum%=MOD;  
    }  
    return sum;  
}  
  
int main() {  
    //freopen("in.txt","r",stdin);  
    Matrix m;  
    while(~scanf("%d%d",&k,&MOD)){  
        for(int i=0;i<maxn;i++)  
            scanf("%d",&arr[i]);  
        init(m);  
        if(k<10) printf("%d\n",k%MOD);  
        else printf("%lld\n",Pow(m));  
    }  
    return 0;  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值