我们考虑简化题意:
由于与运算和或运算在每一位上都是独立的,我们可以考虑对每一位进行计算。
子任务1是全1子矩阵
子任务2是总子矩阵个数减去全0子矩阵
然后就是单调栈原题 :洛谷 3400 仓鼠窝
#includeusing namespace std;#define re register#define ll long long#define gc getchar()inline int read(){ re int x(0),f(1);re char c(gc); while(c>'9'||c<'0')f=c=='-'?-1:1,c=gc; while(c>='0'&&c<='9')x=x*10+c-48,c=gc; return f*x;}const int N=1010,mod=1e9+7;int n,a[N][N],h[N][N],top,s[N];ll ans;int main(){ n=read(); for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) a[i][j]=read(); for(int k=0;k<=31;++k) { for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) { if((a[i][j]>>k)&1) h[i][j]=h[i-1][j]+1; else h[i][j]=0; } for(int i=1;i<=n;++i) { ll an(0);top=0; for(int j=1;j<=n;++j) { an+=h[i][j]; while(top&&h[i][s[top]]>=h[i][j]) an-=(s[top]-s[top-1])*(h[i][s[top--]]-h[i][j]); ans+=an< >k)&1) h[i][j]=0; else h[i][j]=h[i-1][j]+1; } for(int i=1;i<=n;++i) { ll an(0);top=0; for(int j=1;j<=n;++j) { an+=h[i][j]; while(top&&h[i][s[top]]>=h[i][j]) an-=(s[top]-s[top-1])*(h[i][s[top--]]-h[i][j]); ans+=(1LL*i*j-an)<