#3083. 「GXOI / GZOI2019」与或和

题目大意

给定一个\(N\times N\)的矩阵,求所有子矩阵的\(AND(\&)\)之和、\(OR(|)\)之和。

数据范围

\(1\le N\le 10^3\),\(val_{(i,j)} \le 2^{31}-1\)。

题解

一眼题。

对于这种位运算的题,题都不用看完先想拆位,拆位可行那就拆,拆位不可行就不拆。

这里指的拆位可不可行具体指的是答案满不满足对于拆位之后的可加性。

发现这个题所求的是个和,那就果断拆开。

这样的话问题就变成了给定一个\(01\)矩阵求\(AND\)和(\(OR\)同理)。

发现只要是子矩阵中有\(0\)就是\(0\)。

这种存在即可的式子最\(gay\)了。

绝大多数这种存在即可的式子都会依照“正难则反”变成“不存在即可”。

故此我们只需要求全\(1\)子矩阵个数。

这就很好求了,给定一个边长最多是\(1000\)的正方形\(01\)矩阵,问全\(1\)子矩阵个数。

每一行拿单调栈扫一扫就好了。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define N 1010
int ori[N][N],a[N][N],bfr_up[N][N],bfr[N],aft[N],q[N],top;
int bin[31];
const int mod = 1000000007 ;
const int inv4 = 250000002 ;
char *p1,*p2,buf[1000000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
int main()
{
bin[0]=1; for(int i=1;i<=30;i++) bin[i]=bin[i-1]<<1;
int n=rd();
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) ori[i][j]=rd();
int ans1=0,ans2=0;
for(int bt=0;bt<=30;bt++)
{
int now1=0,now2=0;
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
{
a[i][j]=(ori[i][j]>>bt)&1;
if(a[i][j]) bfr_up[i][j]=bfr_up[i-1][j]+1; else bfr_up[i][j]=0;
}
for(int i=1;i<=n;i++)
{
top=0;
for(int j=n;j;j--)
{
while(top&&bfr_up[i][j]<bfr_up[i][q[top]]) bfr[q[top]]=j,top--;
q[++top]=j;
}
while(top) bfr[q[top]]=0,top--;
top=0;
for(int j=1;j<=n;j++)
{
while(top&&bfr_up[i][j]<=bfr_up[i][q[top]]) aft[q[top]]=j,top--;
q[++top]=j;
}
while(top) aft[q[top]]=n+1,top--;
for(int j=1;j<=n;j++) (now1+=(ll)bfr_up[i][j]*(aft[j]-j)*(j-bfr[j])%mod)%=mod;
}
for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
{
a[i][j]^=1;
if(a[i][j]) bfr_up[i][j]=bfr_up[i-1][j]+1; else bfr_up[i][j]=0;
}
for(int i=1;i<=n;i++)
{
top=0;
for(int j=n;j;j--)
{
while(top&&bfr_up[i][j]<bfr_up[i][q[top]]) bfr[q[top]]=j,top--;
q[++top]=j;
}
while(top) bfr[q[top]]=0,top--;
top=0;
for(int j=1;j<=n;j++)
{
while(top&&bfr_up[i][j]<=bfr_up[i][q[top]]) aft[q[top]]=j,top--;
q[++top]=j;
}
while(top) aft[q[top]]=n+1,top--;
for(int j=1;j<=n;j++) (now2+=(ll)bfr_up[i][j]*(aft[j]-j)*(j-bfr[j])%mod)%=mod;
}
now1=(ll)now1*bin[bt]%mod;
now2=(ll)now2*bin[bt]%mod;
(ans1+=now1)%=mod;
(ans2+=((ll)n * n * (n + 1) * (n + 1) % mod * inv4 % mod * bin[bt] % mod-now2 + mod)%mod)%=mod;
}
printf("%d %d\n",ans1,ans2);
return 0;
}

小结

模拟赛中被卡常了,\(LOJ\)也被卡常了。

这种取\(mod\)的题少取两次\(mod\)就好了。

最新文章

  1. Winform绑定数据源的几种方式?
  2. CF #374 (Div. 2) C. Journey dp
  3. 关于mac mini组装普液晶显示器
  4. 【转】Java JDBC连接SQL Server2005错误:通过端口 1433 连接到主机 localhost 的 TCP/IP 连接失败
  5. 浅谈MS-SQL锁机制
  6. 按钮效果 css
  7. 待解决)leetcode 路径和 dfs 线序遍历
  8. Introduce: IEPI.BIATranscribe 图像表格拓写工具
  9. 修改WCF的默认序列化格式
  10. Re.FFT
  11. 一些Linq方法,come on !!
  12. openstack安装-计算节点-nova计算服务安装
  13. opencv人脸识别代码
  14. 【IntelliJ 】IntelliJ IDEA 2017激活码
  15. C#控件之:进度条(ProgressBar)
  16. Codeforces Round #517 (Div. 2, based on Technocup 2019 Elimination Round 2)
  17. statement 对象执行sql语句
  18. 快速排序—三路快排 vs 双基准
  19. web前端--实现前后端分离的心得
  20. [hdu3685]Rotational Painting 凸包 重心

热门文章

  1. ThreadLocal类使用说明
  2. Bzoj 1055: [HAOI2008]玩具取名 (区间DP)
  3. 使用Fiddler抓取Android模拟器中的Android_APP请求
  4. perl:_DATA_ _LINE_ _FILE_
  5. Python日志(logging)模块,shelve,sys模块
  6. Python9-列表-day4
  7. 牛客网暑期ACM多校训练营(第六场) I Team Rocket(线段树)
  8. PAT Basic 1061
  9. PAT Basic 1010
  10. ORACLE 检索某列包含特定字符串的数据表工具存储过程