CF-div2-626-B. Count Subrectangles
先想到,
假如行有n个连续为1,列上有m个连续为1,则可以组成nm大小的矩阵。
比如行1个连续,列2个连续。可以构成c[1][1]=1,c[1][2]=1,size=12=2;
然后就好办了。
先想到一个暴力的思路,然后逐步优化。
1.枚举x
2.枚举y,当x*y == k,就是为了去构成大小为k的矩阵嘛。
3.O(n^2)找出a数组长度为x且全1的个数,找出b数组长度为y且全1的个数,二者相乘(乘法原理,种类个数),累加即可。
考虑优化的方案。
首先枚举y,可以变成计算y,y = k/x(当k%x==0)
然后找出a数组长度为x且全1的个数,可以使用前缀和优化成O(n)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 4e5+10;
int n,m,k;
ll a[maxn],b[maxn],col[maxn],row[maxn];
unordered_map<int,int> mp;
int main(){
cin>>n>>m>>k;
for(int i=1;i<=n;i++) {
cin>>a[i];
row[i] = row[i-1] + a[i];
}
for(int i=1;i<=m;i++) {
cin>>b[i];
col[i] = col[i-1] + b[i];
}
ll ans = 0;
for(int i=1;i<=n;i++){
if(k%i==0) mp[i] = k/i;
}
for(auto it:mp){
int x = it.first;
int y = it.second;
ll cnt1 = 0,cnt2 = 0; //表示能构成行(列)为x(y)的个数
for(int i=1;i<=n-x+1;i++){
if(row[i+x-1] - row[i-1] == x) //如果这段连续长度为x且这一段全为1
cnt1 += 1;
}
for(int i=1;i<=m-y+1;i++){
if(col[i+y-1] - col[i-1] == y) //如果这段连续长度为y且这一段全为1
cnt2 += 1;
}
ans += cnt1*cnt2; //乘法原理 能组成cnt1*cnt2种方案构成size为k的矩形
}
cout<<ans;
return 0;
}
/*
3 3 2
1 0 1
1 1 1
*/