1. 程式人生 > >poj 3233 Matrix Power Series (構造分塊矩陣)

poj 3233 Matrix Power Series (構造分塊矩陣)

題目連結:哆啦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;
}


我的標籤:做個有情懷的程式設計師。