题意:
两个数组a,b(仅有0,1)一个整数k
找出所有c矩阵的子矩阵的大小为k且里面的值都为1
思路:
很显然
时,第i行的数全为
时,第i列的数全为0
我们把
数组处理一下,把连续的1放在一起,相当于把数组压缩一下
然后处理出来
的因子
假设其中一对为
看代码应该就懂了
我做的时候,压缩之后想着把所有的矩阵枚举出来,找符合组成大小为k的矩阵的个数
很明显会超时
那样是一个一个加的
实际应该就是上面的做法,找到相应的个数直接把f1*f2即可
如果我的想法的话需要,找
次,每次找到一个,刚找到6个
正确做法:找cnt1+cnt2次,列找到f1个,行找到f2个,找到
个
summary
虽然想到很简单,但我就是菜啊,菜哭了~~~~
对于矩阵,找到一段满足,往下一列(或者往右一行都应该满足)
代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <vector>
#include <math.h>
#include <map>
#include <queue>
#include <set>
#include <stack>
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
typedef long long ll;
using namespace std;
const int MAXN=4e4+50;
const int inf=0x3f3f3f3f;
const int M=5000*4;
int a[MAXN],b[MAXN];
int aa[MAXN],bb[MAXN],p[MAXN];
int n,m,k;
int cnt1=0,cnt2=0,cnt=0;
int cmp(int a,int b){
return a>b;
}
ll solve(int r,int c){
ll f1=0,f2=0;
for(int i=1;i<=cnt1;i++)
if(aa[i]>=r) f1++;
else break;//因为排过序
for(int i=1;i<=cnt2;i++)
if(bb[i]>=c) f2++;
else break;
return f1*f2;
}
int main()
{
cin>>n>>m>>k;
int x=0;
rep(i,1,n){
scanf("%d",&a[i]);
x+=a[i];
if(a[i]==0){
x=0;
continue;
}
aa[++cnt1]=x;//对a的压缩,里面的是连续1的个数
}
x=0;
rep(i,1,m){
scanf("%d",&b[i]);
x+=b[i];
if(b[i]==0){
x=0;
continue;
}
bb[++cnt2]=x;
}
sort(aa+1,aa+cnt1+1,cmp);//从大到小排序
sort(bb+1,bb+cnt2+1,cmp);
if(cnt1==0||cnt2==0){
cout<<0<<endl;
return 0;
}
for(int i=1;i*i<=k;i++){//分解k的因子
if(k%i==0)p[++cnt]=i;
}
ll ans=0;
for(int i=1;i<=cnt;i++){
int r=p[i],c=k/p[i];
if(r==c)ans+=solve(r,c);//如果r==c,只能算一次,否则会算重复
else ans+=solve(r,c)+solve(c,r);
}
printf("%lld\n",ans);
return 0;
}
/*
*/