hdu 4565 so easy 线性递推+矩阵乘法+快速幂 2013湖南区域邀请赛

本文分享了一道涉及矩阵快速幂算法的编程题解过程,总结了实现过程中容易忽视的关键点,包括处理负数模运算、数据类型的选用、矩阵乘法方向及不同平台输出格式等问题。

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

解题报告链接

题目链接

别人的递推公式写的很详细,我就不写了,我写下应当注意的事项吧。

看了别人的解题报告 大呼一声模板 就开始码,码了三遍~~wa了无数次,还有就是栈溢出等等  我就郁闷了,这个模板是略有不同的。

(1)存在负数的情况  以往做的题都 矩阵中都是正数 而现在出现的负数的情况 对于编译器来讲 -9%2=-1  这个是需要注意的。 最后的结果可能也为负数,所以要加上模的数。

(2)矩阵中的数据类型最好全是long long  带进矩阵中的数最好全是模过的数。

(3)注意矩阵乘法不满足交换律,一定要注意乘法的方向

 (4)杭电中输出不要用%lld 要用%I64d   linux是输出lld ,windows 是I64d 。所以杭电用的是盗版windows server。

下面是代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<math.h>
using namespace std;
#define ll long long
int mm;
struct Matrix {
    int n,m;
    ll a[5][5];
    void clear(){
        n=0;m=0;
        memset(a,0,sizeof(a));
    }
    Matrix operator *(const Matrix b)const{  //重载乘法运算符
        Matrix tmp;
        tmp.clear();
        tmp.n=n;
        tmp.m=b.m;
        for(int i=1;i<=tmp.n;i++)
            for(int j=1;j<=tmp.m;j++)
                for(int k=1;k<=m;k++){
                   tmp.a[i][j]+=a[i][k]*b.a[k][j];
                   tmp.a[i][j]=tmp.a[i][j]%mm;
                }
            return tmp;
    }
}base,ori,ans;
Matrix fun(int n){    //快速幂
    if(n==1)return base;
    Matrix tt=fun(n/2);
    tt=tt*tt;
    if(n%2==1)tt=tt*base;
    return tt;
}



int main()
{
    ll a,b,n;
    ll ansOne,ansTwo;
    while(scanf("%I64d%I64d%I64d%d",&a,&b,&n,&mm)!=EOF){
          a=a%mm;
          ansOne=2*a%mm;
          ansTwo=2*(a*a+b)%mm;
          if(n==0){printf("1\n");continue;}
          if(n==1){printf("%lld\n",ansOne);continue;}
          if(n==2){printf("%lld\n",ansTwo);continue;}
          ori.n=2;ori.m=1;ori.a[1][1]=ansTwo;ori.a[2][1]=ansOne;
          base.n=2;base.m=2;base.a[1][1]=ansOne;base.a[1][2]=b-a*a;base.a[2][1]=1;base.a[2][2]=0;
          Matrix ans=fun(n-2);
          ans=ans*ori;
          if(ans.a[1][1]<0)ans.a[1][1]=(ans.a[1][1]+mm)%mm;
          printf("%I64d\n",ans.a[1][1]);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值