• Codevs No.3147 矩阵乘法2


    2016-06-01 17:33:30

    题目链接: 矩阵乘法2 (Codevs No.3147)

    题目大意:

      给定两个大小相同的正方形矩阵A,B.多次询问,每次求乘后矩阵的一个子矩阵所有元素的和.

    解法:

      首先想到暴力.

        预处理N^3,询问模拟扫,这常数简直瞬间爆炸啊

      当然是可以优化的.

        列出子矩阵的元素表达式,就会发现有一些元素//矩阵乘法2 (Codevs No.3147)
    //矩阵乘法
    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    const int maxn=2010;
    int map1[maxn][maxn];
    int map2[maxn][maxn];
    long long ans;
    int N,M;
    int a,b,c,d;
    int main()
    {
        scanf("%d %d",&N,&M);
        for(int i=1;i<=N;i++)
        {
            for(int j=1;j<=N;j++)
            {
                scanf("%d",&map1[i][j]);
                map1[i][j]+=map1[i-1][j];
            }
        }
        for(int i=1;i<=N;i++)
        {
            for(int j=1;j<=N;j++)
            {
                scanf("%d",&map2[i][j]);
                map2[i][j]+=map2[i][j-1];
            }
        }
        for(int i=1;i<=M;i++)
        {
            ans=0;
            scanf("%d %d %d %d",&a,&b,&c,&d);
            for(int i=1;i<=N;i++)
            {
                int sumxmap2=map2[i][max(b,d)]-map2[i][min(b,d)-1];
                int sumymap1=map1[max(a,c)][i]-map1[min(a,c)-1][i];
                ans+=(long long)sumxmap2*sumymap1;
            }
            printf("%lld ",ans);
        }
        return 0;
    }的乘积可以做乘法分配律

        所以直接放弃求出子矩阵的确切值,按照分配律的特点组合数据.

        我们对A(乘法的时候乘行)进行列前缀和,对B(乘法的时候乘列)进行行前缀和

        最后所有元素的和就可以表示成sigma((A[i][Dbound]-A[i][Ubound-1])*(B[i][Rbound]-B[i][Lbound-1]));

        (Ubound,Dbound,Lbound,Rbound表示小矩阵的上下左右)

     1 //矩阵乘法2 (Codevs No.3147)
     2 //矩阵乘法
     3 #include<stdio.h>
     4 #include<algorithm>
     5 using namespace std;
     6 const int maxn=2010;
     7 int map1[maxn][maxn];
     8 int map2[maxn][maxn];
     9 long long ans;
    10 int N,M;
    11 int a,b,c,d;
    12 int main()
    13 {
    14     scanf("%d %d",&N,&M);
    15     for(int i=1;i<=N;i++)
    16     {
    17         for(int j=1;j<=N;j++)
    18         {
    19             scanf("%d",&map1[i][j]);
    20             map1[i][j]+=map1[i-1][j];
    21         }
    22     }
    23     for(int i=1;i<=N;i++)
    24     {
    25         for(int j=1;j<=N;j++)
    26         {
    27             scanf("%d",&map2[i][j]);
    28             map2[i][j]+=map2[i][j-1];
    29         }
    30     }
    31     for(int i=1;i<=M;i++)
    32     {
    33         ans=0;
    34         scanf("%d %d %d %d",&a,&b,&c,&d);
    35         for(int i=1;i<=N;i++)
    36         {
    37             int sumxmap2=map2[i][max(b,d)]-map2[i][min(b,d)-1];
    38             int sumymap1=map1[max(a,c)][i]-map1[min(a,c)-1][i];
    39             ans+=(long long)sumxmap2*sumymap1;
    40         }
    41         printf("%lld
    ",ans);
    42     }
    43     return 0;
    44 }
  • 相关阅读:
    如何配置android的adb环境变量
    react中 如何异步展示后台接口的提示消息
    java doc 相关
    linux 停止多个 进程...
    maven 打包 war 包含 WEB-INF/lib 目录
    对 ArrayList 进行分页.
    docker 磁盘清理 相关
    vue 在 html 中自定义 tag
    docker 限制 容器内存 使用
    mysql 基本语句
  • 原文地址:https://www.cnblogs.com/Neptune-/p/5550461.html
Copyright © 2020-2023  润新知