题目描述
给出长度分别为
n
,
m
n, m
n,m的
a
,
b
a, b
a,b数组
得出一个
(
c
i
,
j
=
a
i
∗
b
j
)
(c_{i, j} = a_i * b_j)
(ci,j=ai∗bj)的矩阵
求此矩阵的子矩阵权值和在
[
L
,
R
]
[L, R]
[L,R]之间的个数
样例输入
3 3 3 8
3 2 3
2 3 1
样例输出
10
思路
对于一个左上角为
(
x
1
,
y
1
)
(x1, y1)
(x1,y1)右下角为
(
x
2
,
y
2
)
(x2, y2)
(x2,y2)
权值和
a
x
1
∗
(
b
y
1
+
.
.
.
+
b
y
2
)
+
.
.
.
+
a
x
2
∗
(
b
y
1
+
.
.
.
+
b
y
2
)
ax1 * (by1 + ... + by2) + ... + ax2 * (by1 + ... + by2)
ax1∗(by1+...+by2)+...+ax2∗(by1+...+by2)
合并
(
a
x
1
+
.
.
.
+
a
x
2
)
∗
(
b
y
1
+
.
.
.
+
b
y
2
)
(ax1 + ... + ax2) * (by1 + ... + by2)
(ax1+...+ax2)∗(by1+...+by2)
可以知道我们选出的x1和x2与y1和y2并不影响
所以我们可以把所有
(
b
y
1
+
.
.
.
+
b
y
2
)
(by1 + ... + by2)
(by1+...+by2)预处理到一个数组
排个序
然后再枚举
(
a
x
1
+
.
.
.
+
a
x
2
)
=
k
(ax1 + ... + ax2) = k
(ax1+...+ax2)=k
在数组里二分出
k
∗
h
y
i
k * hy_i
k∗hyi在
[
L
,
R
]
[L, R]
[L,R]的个数
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
ll hy[1000250], A[20005], B[20005], p[20005], q[20005];
ll n, m, L, R, t, Ans;
ll init(ll k)
{
ll al, ar, ans = 1e16;
ll l = 1, r = t, mid;
while(l <= r)
{
mid = (l + r) >> 1;
if(hy[mid] * k < L)l = mid + 1;
else ans = mid, r = mid - 1;
}
al = ans;
l = 1, r = t;
ans = -1e16;
while(l <= r)
{
mid = (l + r) >> 1;
if(hy[mid] * k > R)r = mid - 1;
else ans = mid, l = mid + 1;
}
ar = ans;
return max((ll)0, ar - al + 1);
}
int main()
{
scanf("%lld%lld%lld%lld", &n, &m, &L, &R);
for(ll i = 1; i <= n; ++i)
scanf("%lld", &A[i]), p[i] = p[i - 1] + A[i];
for(ll i = 1; i <= m; ++i)
scanf("%lld", &B[i]), q[i] = q[i - 1] + B[i];
for(ll i = 1; i <= m; ++i)
for(ll j = i; j <= m; ++j)
hy[++t] = q[j] - q[i - 1];
sort(hy + 1, hy + t + 1);
for(ll i = 1; i <= n; ++i)
for(ll j = i; j <= n; ++j)
{
ll tt = p[j] - p[i - 1];
Ans += init(max((ll)1, tt));
}
printf("%lld", Ans);
return 0;
}