poj3233 Matrix Power Series,矩阵快速幂

(A个水题也要发一篇,是不是病了)

好吧来看题目,poj3233。

A+A^2+A^3+......

前几天才看到这个求级数的方法,今天就用上了。

设work(A,n)=A+A^2+A^3+.....A^n

当n为偶数,work(A,n)=A+A^2+A^3+.....A^n=A+A^2+A^3+.....A^n/2+(A^n/2)*(A+A^2+A^3+.....A^n/2)=work(A,n/2)*(A^n/2+E);

n为奇数work(A,n)=work(A,n-1)+A^n;

跑得很慢的代码:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define Max_n 34

int n,k,m;

struct mat{
    int s[Max_n][Max_n];
    //int operator[][](const int &a,const int &b){return s[a][b];}
    mat operator *(const mat &b)const{
        int i,j,k,tmp;
        mat ret;

        for(i=1;i<=n;++i){
            for(j=1;j<=n;++j){
                tmp=0;
                for(k=1;k<=n;++k){
                    tmp=(tmp+(s[i][k]*b.s[k][j])%m)%m;
                }
                //printf("             %d %d\n",tmp,m);
                ret.s[i][j]=tmp;
            }
        }
        return ret;
    }
    mat operator +(const mat &b)const{
        int i,j;
        mat ret;
        for(i=1;i<=n;++i){
            for(j=1;j<=n;++j){
                ret.s[i][j]=(s[i][j]+b.s[i][j])%m;
            }
        }
        return ret;
    }
    void inite(){
        int i,j;
        for(i=1;i<=n;++i)
            for(j=1;j<=n;++j){
                if (i==j) s[i][j]=1;else s[i][j]=0;
            }
    }

    void print(){
        int i,j;
        for(i=1;i<=n;++i){
            for(j=1;j<=n;++j){
                printf("%d",s[i][j]);
                if (j!=n) printf(" ");
            }
            printf("\n");
        }
    }

}a,ans;

mat smul(mat b,int t){
    mat ret;
    ret.inite();
    while(t){
        if (t&1){
            ret=ret*b;
            t=t^1;
        }
        else {
            b=b*b;
            t>>=1;
        }
    }
    return ret;
}

mat work(mat c,int k){
    mat E;
    E.inite();
    if (k==0) return E;
    else if (k==1) return c;
    if (k&1) return work(c,k-1)+smul(c,k);
    else return work(c,k/2)*(smul(c,k/2)+E);
}



int main(){
    //freopen("3233in.txt","r",stdin);
    int i,j;
    scanf("%d%d%d",&n,&k,&m);
    for(i=1;i<=n;++i){
        for(j=1;j<=n;++j){
            scanf("%d",&a.s[i][j]);
            a.s[i][j]%=m;
        }
    }

    ans=work(a,k);
    ans.print();
    return 0;
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值