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\n",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\n",ans);
42     }
43     return 0;
44 }

 

posted @ 2016-06-01 17:44  %Neptune%  阅读(204)  评论(0编辑  收藏  举报