【BZOJ】5010: [Fjoi2017]矩阵填数
【算法】离散化+容斥原理
【题意】给定大矩阵,可以每格都可以任意填1~m,给定n个子矩阵,要求满足子矩阵内的最大值为vi,求方案数。
n<=10,h,w<=1w。
【题解】
此题重点之一在于离散化,因为有效坐标很少,离散化后遵循左闭右开计算矩阵点数。
然后对于每个格,能填的最大值是min(m,vi),vi为覆盖到该点的所有小矩阵,就此算出总方案数。
现在多考虑了一些情况,就是每个小矩阵中至少要有一个格子是最大值,不符合的情况需要剔除。
考虑容斥原理,奇加偶减,不过这里是总方案-容斥部分,所以是奇减偶加。
2^n枚举子集,然后对于选中的矩阵为min(vi-1),未选中的矩阵为min(vi),其它为m,即强制选中的矩阵不符合条件。
复杂度O(2^n*[n*n^2+n^2*log n])。
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=,M=; int h,w,m,n,x1[maxn],y1[maxn],x2[maxn],y2[maxn],vx[maxn];
int x[maxn],y[maxn],totx,toty,totv;
int mat[maxn][maxn],map[maxn][maxn],ans,s; int pow(int x,int k){
int as=;
while(k){
if(k&)as=1ll*as*x%M;
x=1ll*x*x%M;
k>>=;
}
return as;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d",&h,&w,&m,&n);
totx=toty=totv=;
x[++totx]=;x[++totx]=h+;
y[++toty]=;y[++toty]=w+;
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i],&vx[i]);
x[++totx]=x1[i];x[++totx]=x2[i]+;
y[++toty]=y1[i];y[++toty]=y2[i]+;
}
sort(x+,x+totx+);totx=unique(x+,x+totx+)-x-;
sort(y+,y+toty+);toty=unique(y+,y+toty+)-y-;
for(int i=;i<totx;i++)for(int j=;j<toty;j++)mat[i][j]=(x[i+]-x[i])*(y[j+]-y[j]);
for(int i=;i<=n;i++){
x1[i]=lower_bound(x+,x+totx+,x1[i])-x;
x2[i]=lower_bound(x+,x+totx+,x2[i]+)-x;
y1[i]=lower_bound(y+,y+toty+,y1[i])-y;
y2[i]=lower_bound(y+,y+toty+,y2[i]+)-y;
}
ans=;
for(int S=;S<(<<n);S++){
int num=;
for(int i=;i<totx;i++)for(int j=;j<toty;j++)map[i][j]=m;
for(int k=;k<=n;k++){
int mx=vx[k];
if(S&(<<(k-))){mx--;num++;}
for(int i=x1[k];i<x2[k];i++)for(int j=y1[k];j<y2[k];j++)map[i][j]=min(map[i][j],mx);
}
if(num&)s=-;else s=;
for(int i=;i<totx;i++)for(int j=;j<toty;j++)s=1ll*s*pow(map[i][j],mat[i][j])%M;
ans=(ans+s)%M;
}
printf("%d\n",(ans+M)%M);
}
return ;
}
可以优化一下,统计每个策略时本来是枚举所有点,改为枚举所有权值,因为快速幂取模很慢,所以速度得到了巨大的提升……
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=,M=; int h,w,m,n,x1[maxn],y1[maxn],x2[maxn],y2[maxn],vx[maxn];
int x[maxn],y[maxn],v[maxn],totx,toty,totv;
int mat[maxn][maxn],map[maxn][maxn],ans,s,c[maxn]; int pow(int x,int k){
int as=;
while(k){
if(k&)as=1ll*as*x%M;
x=1ll*x*x%M;
k>>=;
}
return as;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d",&h,&w,&m,&n);
totx=toty=totv=;
x[++totx]=;x[++totx]=h+;
y[++toty]=;y[++toty]=w+;
v[++totv]=m;
for(int i=;i<=n;i++){
scanf("%d%d%d%d%d",&x1[i],&y1[i],&x2[i],&y2[i],&vx[i]);
x[++totx]=x1[i];x[++totx]=x2[i]+;
y[++toty]=y1[i];y[++toty]=y2[i]+;
v[++totv]=vx[i];v[++totv]=vx[i]-;
}
sort(x+,x+totx+);totx=unique(x+,x+totx+)-x-;
sort(y+,y+toty+);toty=unique(y+,y+toty+)-y-;
sort(v+,v+totv+);totv=unique(v+,v+totv+)-v-;
for(int i=;i<totx;i++)for(int j=;j<toty;j++)mat[i][j]=(x[i+]-x[i])*(y[j+]-y[j]);
for(int i=;i<=n;i++){
x1[i]=lower_bound(x+,x+totx+,x1[i])-x;
x2[i]=lower_bound(x+,x+totx+,x2[i]+)-x;
y1[i]=lower_bound(y+,y+toty+,y1[i])-y;
y2[i]=lower_bound(y+,y+toty+,y2[i]+)-y;
vx[i]=lower_bound(v+,v+totv+,vx[i])-v;
}
ans=;
for(int S=;S<(<<n);S++){
int num=;
for(int i=;i<totx;i++)for(int j=;j<toty;j++)map[i][j]=totv;
for(int k=;k<=n;k++){
int mx=vx[k];
if(S&(<<(k-))){mx--;num++;}
for(int i=x1[k];i<x2[k];i++)for(int j=y1[k];j<y2[k];j++)map[i][j]=min(map[i][j],mx);
}
if(num&)s=-;else s=;
for(int i=;i<=totv;i++)c[i]=;
for(int i=;i<totx;i++)for(int j=;j<toty;j++)c[map[i][j]]+=mat[i][j];
for(int i=;i<=totv;i++)s=1ll*s*pow(v[i],c[i])%M;
ans=(ans+s)%M;
}
printf("%d\n",(ans+M)%M);
}
return ;
}
【BZOJ】5010: [Fjoi2017]矩阵填数的更多相关文章
- bzoj 5010: [Fjoi2017]矩阵填数
Description 给定一个 h*w 的矩阵,矩阵的行编号从上到下依次为 1..h,列编号从左到右依次1..w.在这个矩阵中你需要在每 个格子中填入 1..m 中的某个数.给这个矩阵填数的时候有一 ...
- [BZOJ5010][FJOI2017]矩阵填数(状压DP)
5010: [Fjoi2017]矩阵填数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 90 Solved: 45[Submit][Status][ ...
- [FJOI2017]矩阵填数——容斥
参考:题解 P3813 [[FJOI2017]矩阵填数] 题目大意: 给定一个 h∗w 的矩阵,矩阵的行编号从上到下依次为 1...h ,列编号从左到右依次 1...w . 在这个矩阵中你需要在每个格 ...
- P3813 [FJOI2017]矩阵填数(组合数学)
P3813 [FJOI2017]矩阵填数 shadowice1984说:看到计数想容斥........ 这题中,我们把图分成若干块,每块的最大值域不同 蓝后根据乘法原理把每块的方案数(互不相干)相乘. ...
- bzoj5010: [Fjoi2017]矩阵填数
Description 给定一个 h*w 的矩阵,矩阵的行编号从上到下依次为 1..h,列编号从左到右依次1..w.在这个矩阵中你需要在每 个格子中填入 1..m 中的某个数.给这个矩阵填数的时候有一 ...
- [luogu P3813] [FJOI2017] 矩阵填数 解题报告 (容斥原理)
题目链接: https://www.luogu.org/problemnew/show/P3813 题目: 给定一个 h*w的矩阵,矩阵的行编号从上到下依次为 1..h,列编号从左到右依次1..w. ...
- BZOJ5010 FJOI2017矩阵填数(容斥原理)
如果只考虑某个子矩阵的话,其最大值为v的方案数显然是vsize-(v-1)size.问题在于处理子矩阵间的交叉情况. 如果两个交叉的子矩阵所要求的最大值不同,可以直接把交叉部分划给所要求的最大值较小的 ...
- P3813 [FJOI2017]矩阵填数
传送门 矩阵很大,但是发现 $n$ 很小,从这边考虑,对于一个一堆小矩阵放在一起的情况 考虑把每一块单独考虑然后方案再乘起来 但是这些奇怪的东西很不好考虑 所以暴力一点,直接拆成一个个小块 但是这样我 ...
- [FJOI2017]矩阵填数
[Luogu3813] [LOJ2280] 写得很好的题解 \(1.\)离散化出每一块内部不互相影响的块 \(2.\)\(dp[i][j]\)为前 \(i\) 种重叠块其中有 \(j\) 这些状态的矩 ...
随机推荐
- spring boot 连接mysql 错误The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one
1.spring boot 整合mybatis 连接mysql时错误 The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or repr ...
- react实现网站换肤功能
一.目标 提供几种主题色给用户选择,然后根据用户的选择改变应用的主题色: 二.实现原理 1.准备不同主题色的样式文件: 2.将用户的选择记录在本地缓存中: 3.每次进入应用时,读取缓存 ...
- Java串口编程学习1-环境配置(64位Win7)
最近在做zigbee的课程设计,需要Java实现对串口数据的读写操作. 网上找了很多代码,好像都比较过时了,直接拿来用没法跑通……QAQ……然后自己写个教程留底,如有不当之处还请各位路过的大神赐教. ...
- JMS实战——ActiveMQ实现Pub-Sub
前言 上篇博客<JMS实战--ActiveMQ>介绍了ActiveMQ的安装,并实现了简单的PTP模型.这篇博客我们来看一下Pub-Sub模型,之后来总结一下JMS. 实现 项目结构 其中 ...
- js计算当前日期上一个月和下一个月
/** * 获取上一个月 * * @date 格式为yyyy-mm-dd的日期,如:2014-01-25 */ funct ...
- Zebra - zebra command to get printer error and warning status
1 Flag2 Nibble 16-93 Nibble 8-44 Nibble 35 Nibble 26 Nibble 1
- [转]掌握 Dojo 工具包,第 2 部分: XHR 框架与 Dojo
作者:secooler 快乐的DBA Ajax 的兴起改变了传统的 B/S 结构应用程序中以页面为单位的交互模式,Ajax 引入的局部刷新机制带来了更好的用户体验,促使浏览器中的页面开始向应用程序发展 ...
- 用 xampp 在ubuntu 下配置php 运行环境 lampp
在linux下搭建php的运行环境,可以分别安装apache.mysql .php .phpmyadmin,也可以安装xampp(apache.mysql .php .phpmyadmin)集成包 ...
- 高中信息技术《算法与程序设计VB(选修)》知识要点
原博主: http://blog.sina.com.cn/buyanshibai [转载] (一)算法 1.定义 相关题解: 1算法:就是解决问题的方法和步骤.算法是程序设计的“灵魂”,算法+数据结构 ...
- DataBase -- FUNCTION
SQL拥有很多课用于计数和计算的内建函数. SELECT function(列) FROM 表 合计函数(Aggregate Functions) Aggregate函数的操作面向一系列的值,并返回一 ...