poj 3233 Matrix Power Series (构造分块矩阵)

版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/84480922

题目链接:哆啦A梦传送门

题意:自己看。

参考博客:神犇

题解:分块矩阵:分块矩阵可以构造求和。

例如:我们可以这样构造,

S1=\begin{bmatrix} A &{\color{Red} E} \\ 0& E \end{bmatrix},S2=\begin{bmatrix} A^2 &{\color{Red} A+E} \\ 0&E \end{bmatrix},...,S(k+1)=\begin{bmatrix} A^k & {\color{Red} A^k+A^(k-1)+...+A+E}\\ 0& E \end{bmatrix}

还需注意一点的是:算完S(k+1),取出右上角矩阵分块后,还需减掉单位矩阵E。

代码不是我写的,我就按自己习惯改了下变量,主要是博主写的太溜了,不搬都对不起他:

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
typedef long long LL;
LL mod;
int n,k;

struct mat{
    LL a[70][70];
    mat(){ memset(a,0,sizeof(a));}

    mat operator * (const mat y)
    {
        mat ans;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++)
            ans.a[i][j]=(ans.a[i][j]+a[i][k]*y.a[k][j])%mod;
        return ans;
    }

    mat operator + (const mat y)
    {
        mat ans;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            ans.a[i][j]=(ans.a[i][j]+y.a[i][j])%mod;
        return ans;
    }

};

mat mat_pow(mat x,int k)
{
    mat ans;
    for(int i=1;i<=n;i++) ans.a[i][i]=1;

    while(k)
    {
        if(k&1) ans=ans*x;
        x=x*x;
        k>>=1;
    }
    return ans;
}

int main()
{

    while(~scanf("%d%d%lld",&n,&k,&mod))
    {

        mat p;

        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++){
                scanf("%lld",&p.a[i][j]); ///左上角矩阵
                p.a[i][j]%mod;
            }
            p.a[i+n][i+n]=1; ///构造右下角单位阵
            p.a[i][i+n]=1;///构造左上角单位阵
        }

        n<<=1;
        mat item=mat_pow(p,k+1);
        n>>=1;

        mat ans;
        for(int i=1;i<=n;i++)
            for(int j=n+1;j<=n*2;j++) ///把右上角的矩阵分块取出
            ans.a[i][j-n]=item.a[i][j];

        for(int i=1;i<=n;i++){
            ans.a[i][i]--; ///减去单位矩阵
            if(ans.a[i][i]<0) ans.a[i][i]+=mod;
        }

        for(int i=1;i<=n;i++) ///输出
        {
            for(int j=1;j<=n;j++)
                printf("%lld ",ans.a[i][j]);
            puts("");
        }
    }
    return 0;
}


我的标签:做个有情怀的程序员。

猜你喜欢

转载自blog.csdn.net/LJD201724114126/article/details/84480922