BZOJ 2901: 矩阵求和

2901: 矩阵求和

Time Limit: 20 Sec  Memory Limit: 256 MB
Submit: 411  Solved: 216
[Submit][Status][Discuss]

Description

给出两个n*n的矩阵,m次询问它们的积中给定子矩阵的数值和。
 

Input

第一行两个正整数n,m。
接下来n行,每行n个非负整数,表示第一个矩阵。
接下来n行,每行n个非负整数,表示第二个矩阵。
接下来m行,每行四个正整数a,b,c,d,表示询问第一个矩阵与第二个矩阵的积中,以第a行第b列与第c行第d列为顶点的子矩阵中的元素和。
 

Output

对每次询问,输出一行一个整数,表示该次询问的答案。
 

Sample Input

3 2
1 9 8
3 2 0
1 8 3
9 8 4
0 5 15
1 9 6
1 1 3 3
2 3 1 2

Sample Output

661
388

【数据规模和约定】
对30%的数据满足,n <= 100。
对100%的数据满足,n <= 2000,m <= 50000,输入数据中矩阵元素 < 100,a,b,c,d <= n。

HINT

 

Source

 
[Submit][Status][Discuss]

 

经典题目,然后我忘了怎么做了,然后就被高一学长教做人了……

 

不妨设答案为乘积矩阵的第a行到第c行,第b行到第d行的元素之和。

 

$$\sum_{i=a}^{c} \sum_{j=b}^{d} \sum_{k=1}^{n} A_{i,k}B_{k,j}$$

$$\sum_{k=1}^{n} \sum_{i=a}^{c} \sum_{j=b}^{d} A_{i,k}B_{k,j}$$

$$\sum_{k=1}^{n} (\sum_{i=a}^{c}{A_{i,k}}) (\sum_{j=b}^{d}{B_{k,j}})$$

 

然后对两个矩阵进行前缀和预处理,每次查询的时候暴力枚举k就可以。卡常技巧也是很重要的……

 

 1 #include <cstdio>
 2 
 3 #define siz (1 << 20)
 4 #define frd fread(hd = buf, 1, siz, stdin)
 5 #define gtc (hd == tl ? (frd, *hd++) : *hd++)
 6 
 7 char buf[siz];
 8 char *hd = buf + siz;
 9 char *tl = buf + siz;
10 
11 inline int nextInt(void)
12 {
13     int r = 0, c = gtc;
14     
15     for (; c < 48; c = gtc);
16     
17     for (; c > 47; c = gtc)
18         r = r * 10 + c - '0';
19     
20     return r;
21 }
22 
23 #undef siz
24 #undef frd
25 #undef gtc
26 
27 #define mxn 2005
28 #define mxm 50005
29 #define lnt long long
30 #define rnt register int
31 
32 int n, m;
33 lnt A[mxn][mxn];
34 lnt B[mxn][mxn];
35 
36 signed main(void)
37 {
38 #ifndef ONLINE_JUDGE
39     freopen("in", "r", stdin);
40 #endif
41     
42     n = nextInt();
43     m = nextInt();
44     
45     for (rnt i = 1; i <= n; ++i)
46         for (rnt j = 1; j <= n; ++j)
47             A[i][j] = nextInt() + A[i - 1][j];
48     
49     for (rnt i = 1; i <= n; ++i)
50         for (rnt j = 1; j <= n; ++j)
51             B[i][j] = nextInt() + B[i][j - 1];
52     
53     while (m--)
54     {
55         static int a, b, c, d;
56 
57         a = nextInt();
58         c = nextInt();
59         b = nextInt();
60         d = nextInt();
61 
62 #define swap(x, y) (x ^= y ^= x ^= y)
63         
64         if (a > b)swap(a, b);
65         if (c > d)swap(c, d); 
66 
67         lnt ans = 0;
68         
69         for (rnt k = 1; k <= n; ++k)
70             ans += (A[b][k] - A[a - 1][k]) * (B[k][d] - B[k][c - 1]);
71         
72         printf("%lld\n", ans);
73     }
74 }

 

@Author: YouSiki

 

posted @ 2017-03-12 08:53  YouSiki  阅读(416)  评论(0编辑  收藏  举报