题意
两个数组相乘后得n*m的矩形,求矩形中子矩形(仅包含1)面积为k的有多少个。
思路
面积算出来要是K的话那就有几种可能的矩形,这些可能的矩形的长和宽就是K的因子,再有一个我多画了几个后发现一旦有一个0他所在的那一行或者那一列就会都是0也就把n*m这个大的矩形分割了,因为只有0和1 ,所以在a数组中一段连续的1乘了b数组里的一位之后就会变成某一个分割开的子矩形的边(Ci,j=ai*bj),所以算出在某一种因子的搭配下在两个数组中能找到多少连续不同的边,相乘便是该种搭配下所有满足条件的子矩形,然后遍历所有的因子,总方案数不断累加即可。
这题搞了我好久难受😫
AC代码
#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;
typedef long long LL;//40000*40000会爆int
int a[40005],b[40005],c[100100];
int main()
{
int n,m,k,e=0;
cin>>n>>m>>k;
for(int i=0;i<n;i++)
cin>>a[i];
for(int i=0;i<m;i++)
cin>>b[i];
for(int i=1;i*i<=k;i++)//求出K的所有因子
{
if(k%i==0)
{
c[e++]=i;
if(i==k/i)
continue;//重复就不存了
c[e++]=k/i;
}
}
LL ans=0,cnt,x,y;//x为a数组的连续长度,y为b数组连续长度
for(int i=0;i<e;i++)
{
cnt=0,x=0,y=0;
for(int j=0;j<n;j++)//在a数组当中找符合的连续长度
{
if(a[j])//1
cnt++;
else//被分割就归0
cnt=0;
if(cnt==c[i])//当长度符合计数
{
cnt--;//类似尺取一样把左端点前进一位
x++;
}
}
cnt=0;
for(int j=0;j<m;j++)//同样的在b数组里进行查找
{
if(b[j])
cnt++;
else
cnt=0;
if(cnt==k/c[i])//要是配对的因子,面积要是K
{
cnt--;
y++;
}
}
ans+=x*y;//把每种因子方案累加
}
cout<<ans<<endl;
return 0;
}