Codeforces Round # 626 B. Count Subrectangles (thinking)

Portal

Meaning of the questions:

Two arrays a, b (0, only) an integer k
c i , j = a i b j c_{i,j}=a_i*b_j
Identify all sub-matrix size of the matrix is ​​c and k values ​​which are 1

Ideas:

obviously a [ i ] = 0 a[i]=0 , the number of i-th row are all 0 b [ i ] = 0 0,b[i]=0 , the number of i-th row of all zeros
we a , b a,b array to handle it, the consecutive 1s together, compress the array corresponds to the
process then out k k factor
is assumed as one pair r , c r c = k r,c(r*c=k)
a r , f 1 We just look at the value of a compression array which has several larger than r, assuming a f1
b c , f 2 B compressed inside the array values ​​are greater than the number c, assuming a f2
+ = f 1 f 2 Result + = f1 * f2 can
look at the code should be to understand the

When I did, after thinking about all the compressed matrix enumerated, looking for compliance with the composition of the matrix size is the number of k's
obviously time out
as a plus is a
practical approach should be the top, find the corresponding number directly to the f1 * f2 can
Here Insert Picture Description
if I thought then need to find c n t 1 c n t 2 cnt1*cnt2 times, each time to find a just find six
right approach: find cnt1 + cnt2 times, a column found f1, f2 a row is found, found f 1 f 2 = 6 f1*f2=6 Ge

summary

Although the thought is very simple, but I just ah vegetables, vegetable cry ~ ~ ~ ~
For the matrix, find some satisfaction, down one (or right line should meet)

Code:

#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;
}
/*

*/
Published 158 original articles · won praise 15 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_44091178/article/details/104724297