POJ3233 Matrix Power Series

POJ3233 Matrix Power Series

题意:
i=1nAi (k<=109)

思路

大神Cai曾出过一道类似的,不过那个还更难;
框架就是二分加快速幂
对于 i=1nAi 我们可以将该式分解为A= i=1n/2Ai ,观察到只需要将A式乘上一个 Ab/2 ,那么就可以得到B= i=n/2+1nAi+b/2 ,原式=A+B;
如果n是个偶数,那么A+B就可以了,如果n是个奇数,那么可以换一个东西(迷)
A= i=1n/2Ai ,B= A(n+1)/2 ,那么将A*B得到C= i=(b+1)/2+1nAi+(b+1)/2 ,那么原式还差一个 A(n+1)/2 ,所以加上凑好项了:

i=1nAi=i=1n/2Ai+i=(b+1)/2+1nAi+(b+1)/2+A(n+1)/2=A+B+C

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define Rep(i,s,t)  for(int i=s;i<=t;i++)

struct Mat{
    int m[31][31];
};

Mat a,init;

int n,k,MOD;

Mat Mul(Mat A,Mat B)
{
    Mat c;
    memset(c.m,0,sizeof c.m);
    Rep(i,1,n)  Rep(j,1,n)  Rep(k,1,n)
        c.m[i][j]=(c.m[i][j]+A.m[i][k]*B.m[k][j])%MOD;
    return c;
}

Mat Add(Mat A,Mat B)
{
    Mat c;
    memset(c.m,0,sizeof c.m);
    Rep(i,1,n)  Rep(j,1,n)      
        c.m[i][j]=(A.m[i][j]+B.m[i][j])%MOD;
    return c;
}

Mat pow(Mat A,int k)
{
    Mat ans=A,p=A;
    k--;
    while(k)
    {
        if(k & 1)   ans=Mul(ans,p);
        p=Mul(p,p);
        k>>=1;
    }
    return ans;
}



Mat Sum(Mat A,int k)
{
    if(k==1)    return a;
    Mat C=Sum(A,k>>1);
    if(k & 1)   {
        Mat K=pow(A,(k>>1)+1);
        C=Add(Mul(C,K),Add(C,K));   
    }
    else {
            Mat K=pow(A,k>>1);
            C=Add(Mul(C,K),C);
    }
    return C;
}

int main()
{
    while(scanf("%d%d%d",&n,&k,&MOD)!=EOF)
    {
        memset(a.m,0,sizeof a.m);
        Rep(i,1,n)  Rep(j,1,n)  {scanf("%d",&a.m[i][j]);init.m[i][j]=(i==j);}
        a=Sum(a,k);
        Rep(i,1,n)  {Rep(j,1,n-1)   printf("%d ",a.m[i][j]);printf("%d\n",a.m[i][n]);}
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值