框架
「LibreOJ β Round #4」框架
内存限制:256 MiB时间限制:1000 ms标准输入输出
题目类型:传统评测方式:文本比较
题目描述
有一个 n×mn\times mn×m 的矩形框架,但其中有些边被删除了。qmqmqm想知道剩余部分中还有多少完整的正方形。
输入格式
输入第一行包含两个正整数 n,mn,mn,m。
之后 nnn 行,每行 m−1m-1m−1 个空格隔开的整数为 000 或 111,表示横向边的存在情况。
之后 n−1n-1n−1 行,每行 mmm 个空格隔开的整数为 000 或 111,表示竖向边的存在情况。
输出格式
输出一行一个整数表示剩余完整正方形的个数。
样例
样例输入
3 3
1 1
0 1
1 1
1 1 1
1 0 1
样例输出
2
样例解释
剩余框架为
数据范围与提示
2≤n,m≤1032 \leq n,m \leq 10^32≤n,m≤103
分析:要求正方形的个数;
直接暴力是n^4的,考虑bitset可以优化掉其中两维;
枚举两行n^2,然后bitset快速判断即可;
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #include <cassert> #include <ctime> #define rep(i,m,n) for(i=m;i<=(int)n;i++) #define inf 0x3f3f3f3f #define mod 998244353 #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") #define ls (rt<<1) #define rs (rt<<1|1) #define all(x) x.begin(),x.end() const int maxn=1e3+10; const int N=4e5+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p%mod;p=p*p%mod;q>>=1;}return f;} int n,m,k,t; bitset<maxn>st[maxn][maxn],h[maxn]; int main(){ int i,j; scanf("%d%d",&n,&m); rep(i,1,n)rep(j,1,m-1) { scanf("%d",&k); st[i][1][j]=k; } rep(i,1,n)rep(j,2,m) { st[i][j]=(st[i][j-1]&(st[i][j-1]>>1)); } rep(i,1,n-1)rep(j,1,m) { scanf("%d",&k); h[i][j]=k; } bitset<maxn>tmp; int ret=0; rep(i,1,n)rep(j,i+1,n) { if(j==i+1)tmp=h[i]; else tmp&=h[j-1]; ret+=(tmp&(tmp>>(j-i))&st[i][j-i]&st[j][j-i]).count(); } printf("%d\n",ret); return 0; }