zoukankan      html  css  js  c++  java
  • CF-div2-626-B. Count Subrectangles

    先想到,
    假如行有n个连续为1,列上有m个连续为1,则可以组成nm大小的矩阵。
    比如行1个连续,列2个连续。可以构成c[1][1]=1,c[1][2]=1,size=1
    2=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
    */
    
  • 相关阅读:
    C# 串口通信总结
    配置文件的读写
    配置文件入门
    锁机制与原子操作 <第四篇>
    线程池 异步I/O线程 <第三篇>
    线程池之ThreadPool类与辅助线程
    这一篇sigmoid和softmax的比较,讲的不错
    今天看到的关于深度学习的一篇文章,可以好好学习下
    git各种命令 & git merge和git rebase的区别
    ORA-19815,ORA-19809 :limit exceeded for recovery files
  • 原文地址:https://www.cnblogs.com/fisherss/p/12450493.html
Copyright © 2011-2022 走看看