题目链接:

https://www.luogu.org/problemnew/show/P3813

题目:

给定一个 h*w的矩阵,矩阵的行编号从上到下依次为 1..h,列编号从左到右依次1..w。

在这个矩阵中你需要在每个格子中填入 1..m中的某个数。

给这个矩阵填数的时候有一些限制,给定 n 个该矩阵的子矩阵,以及该子矩阵的最大值 v,要求你所填的方案满足该子矩阵的最大值为 v。

现在,你的任务是求出有多少种填数的方案满足 n 个限制。

两种方案是不一样的当且仅当两个方案至少存在一个格子上有不同的数。由于答案可能很大,你只需要输出答案 mod 1,000,000,007

题解:

对于每个格,能填的最⼤值是 $min(m,v_i)$,$v_i$ 为覆盖到该点的所有⼩矩阵的预设答案,这就是总⽅案数。

考虑容斥原理,奇减偶加。总方案数-一个不合法的方案数+两个不合法的方案数...

离散化后 $2^n$ 枚举⼦集,然后对于选中的矩阵为 $min(v_i−1)$,即强制让选中的⼦矩阵的最⼤值⼩于预设的答案(总方案里一个矩阵里所有的元素都小于等于这个矩阵的v)

这⼀步由于离散化的原因,可以直接暴⼒ for 遍历所有在⼦ 矩阵内的位置。 复杂度:$O(2^n n^3)$

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll; const int N=;
const ll mo=1e9+;
int h,w,m,n,vx,vy,vp;
int ma[N][],dx[N],dy[N],mv[N],a[N][N],mp[N][N];
ll vv[N],tong[N];
inline int read(){
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
ll qpow(ll a,ll b){
ll re=;
for (;b;b>>=,a=a*a%mo) if (b&) re=re*a%mo;
return re;
}
int main()
{
int T=read();
while (T--)
{
h=read();w=read();m=read();n=read();
vx=vy=vp=;
dx[++vx]=;dx[++vx]=h+;
dy[++vy]=;dy[++vy]=w+;
vv[++vp]=m;
for (int i=;i<=n;i++)
{
ma[i][]=read();ma[i][]=read();ma[i][]=read();ma[i][]=read();mv[i]=read();
dx[++vx]=ma[i][];dx[++vx]=ma[i][]+;
dy[++vy]=ma[i][];dy[++vy]=ma[i][]+;
vv[++vp]=mv[i];vv[++vp]=mv[i]-;
}
sort(dx+,dx++vx);
sort(dy+,dy++vy);
sort(vv+,vv++vp);
vx=unique(dx+,dx++vx)-dx-;
vy=unique(dy+,dy++vy)-dy-;
vp=unique(vv+,vv++vp)-vv-;
for (int i=;i<vx;i++)//<号不是<=号,因为最后一个是无效的位置
for (int j=;j<vy;j++) a[i][j]=(dx[i+]-dx[i])*(dy[j+]-dy[j]);
for (int i=;i<=n;i++)
{
ma[i][]=lower_bound(dx+,dx++vx,ma[i][])-dx;
ma[i][]=lower_bound(dx+,dx++vx,ma[i][]+)-dx;
ma[i][]=lower_bound(dy+,dy++vy,ma[i][])-dy;
ma[i][]=lower_bound(dy+,dy++vy,ma[i][]+)-dy;
mv[i]=lower_bound(vv+,vv++vp,mv[i])-vv;
}
ll ans=;
for (int S=;S<(<<n);S++)
{
for (int i=;i<vx;i++)
for (int j=;j<vy;j++) mp[i][j]=vp;
ll s=;
for (int i=;i<n;i++)
{
int v=mv[i+];
if (S>>i&) v--,s=-s;
for (int j=ma[i+][];j<ma[i+][];j++)
for (int k=ma[i+][];k<ma[i+][];k++) mp[j][k]=min(mp[j][k],v);
}
for (int i=;i<=vp;i++) tong[i]=;
for (int i=;i<vx;i++)
for (int j=;j<vy;j++) tong[mp[i][j]]+=a[i][j];
for (int i=;i<=vp;i++) s=s*qpow(vv[i],tong[i])%mo;
ans=(ans+s)%mo;
}
ans=(ans%mo+mo)%mo;
printf("%lld\n",ans);
}
return ;
}

最新文章

  1. iframe自动高度
  2. 【uoj128】 NOI2015—软件包管理器
  3. 几乎所有的html + css 内容的编写, 都可以通过emmet来写
  4. service里面弹出对话框
  5. Lintcode 175 Invert Binary Tree
  6. Java 集合深入理解(6):AbstractList
  7. Sqli-labs less 38
  8. AS3.0声明静态属性和静态方法
  9. 一个ajax实现表单上传文件的神器 formdata
  10. 老李谈HTTP1.1的长连接 1
  11. python 标准库 -- subprocess
  12. mybatis入门篇基——基本配置与参数说明
  13. 浴室沉思:聊聊DAL和Repository
  14. Eclipse For JavaEE安装、配置、测试
  15. captive portal
  16. python 怎么让list里面设置NAN numpy.nan
  17. 学习笔记-AngularJs(五)
  18. IDEA 文件列表隐藏某后缀文件
  19. 【技巧】如何清空SQLServer的日志文件
  20. 如何设置VMware中Linux命令行环境全屏

热门文章

  1. 【POJ 1741】 Tree
  2. [Swift]二进制、八进制、十进制、十六进制之间的转换
  3. CentOS7开启网络配置
  4. php基础知识(一)--2017-04-14
  5. Fine-tuning CaffeNet for Style Recognition on “Flickr Style” Data 数据下载遇到的问题
  6. synchronized同步机制,修饰类和修饰对象的区别
  7. vue2.0中关于active-class
  8. [ RESTful ] [ API ] 有用的資訊
  9. 小数据量csv文件数据导入数据库(思路)
  10. C++内存分配方式——小结