zoukankan      html  css  js  c++  java
  • HDU_4965 Fast Matrix Calculation 2014多校9 矩阵快速幂+机智的矩阵结合律

    一开始看这个题目以为是个裸的矩阵快速幂的题目,

    后来发现会超时,超就超在  M = C^(N*N). 这个操作,而C本身是个N*N的矩阵,N最大为1000。

    但是这里有个巧妙的地方就是 C的来源其实 是= A*B, A为一个N*k的矩阵,B为一个k*N的矩阵,k最大为10,突破的就在这里,矩阵的结合律要用起来

    即我先不把A*B结合,我先把B*A结合,这样M不是要C^N*N吗,就先把里面N*N个(B*A)算出来,就10*10再乘以logN*N即可。最后再两端乘一下A和B即可

    也挺机智的,我没想到结合律。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL __int64
    using namespace std;
    LL matA[1010][10],matB[10][1010];
    LL matC[1010][10];
    LL MM[1010][1010];
    int n,k;
    struct Mat
    {
        LL mat[10][10];
    }E;
    Mat operator *(Mat a,Mat b)
    {
        Mat c;
        for (int i=0;i<k;i++)
        for (int j=0;j<k;j++){
            c.mat[i][j]=0;
            for (int w=0;w<k;w++){
                c.mat[i][j]+=a.mat[i][w]*b.mat[w][j];
                c.mat[i][j]%=6;
            }
        }
        return c;
    }
    Mat operator ^(Mat a,int x)
    {
        Mat c=E;
        for (int i=x;i;i>>=1){
            if (i&1){
                c=c*a;
            }
            a=a*a;
        }
        return c;
    }
    int main()
    {
        memset(E.mat,0,sizeof E.mat);
        for (int i=0;i<10;i++) E.mat[i][i]=1;
        while (scanf("%d%d",&n,&k)!=EOF)
        {
            if (n==0 && k==0) break;
            for (int i=0;i<n;i++)
                for (int j=0;j<k;j++) scanf("%I64d",&matA[i][j]);
            for (int i=0;i<k;i++)
                for (int j=0;j<n;j++) scanf("%I64d",&matB[i][j]);
            Mat a;
            for (int i=0;i<k;i++)
                for (int j=0;j<k;j++){
                   a.mat[i][j]=0;
                   for (int w=0;w<n;w++){
                     a.mat[i][j]+=matB[i][w]*matA[w][j];
                   }
                   //cout<<i<<" aaa "<<j<<" "<<a.mat[i][j]<<endl;
                }
    
            Mat M=a^(n*n-1);
    
            for (int i=0;i<n;i++)
            for (int j=0;j<k;j++){
                matC[i][j]=0;
                for (int w=0;w<k;w++)
                     matC[i][j]+=matA[i][w]*M.mat[w][j];
               // cout<<matC[i][j]<<" Matc "<<endl;
            }
            int ans=0;
            for (int i=0;i<n;i++)
            for (int j=0;j<n;j++){
                MM[i][j]=0;
                for (int w=0;w<k;w++){
                    MM[i][j]+=matC[i][w]*matB[w][j];
                }
               // cout<<MM[i][j]<<" qwe "<<endl;
                ans+=MM[i][j]%6;
            }
            printf("%d
    ",ans);
        }
        return 0;
    
    }
    

      

  • 相关阅读:
    双11专刊|云原生数据仓库AnalyticDB支撑双11,大幅提升分析实时性和用户体验
    LeetCode_Binary Tree Inorder Traversal
    LeetCode_4Sum
    LeetCode_Add Binary
    LeetCode_Add Two Numbers
    LeetCode_3Sum Closest
    Building CEGUI with Ogre 1.8.1
    LeetCode_3Sum
    LeetCode_Climbing Stairs
    LeetCode_Binary Tree Level Order Traversal
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3933025.html
Copyright © 2011-2022 走看看