P3813 [FJOI2017]矩阵填数
矩阵很大,但是发现 $n$ 很小,从这边考虑,对于一个一堆小矩阵放在一起的情况
考虑把每一块单独考虑然后方案再乘起来
但是这些奇怪的东西很不好考虑
所以暴力一点,直接拆成一个个小块
但是这样我们还要考虑到小矩形的限制,设 $f[i][S]$ 表示现在考虑完第 $i$ 个小块,小矩形的限制满足的状态为 $S$ 时的方案数
发现这些小块不会跨过矩形,维护每个小块的限制(即这个块能填的最大的数)$Mx$,以及这个小块填最大数时,能使哪些小矩形满足限制 ($P$)
设小块的面积为 $S$,那么如果下一小矩形不填最大数,则转移到 $f[i+1][S]$,贡献方案数为 $(Mx[i+1]-1)^{S[i+1]}$
如果下一小矩形填最大数,则转移到 $f[i+1][S|P[i+1]]$,贡献为总方案数-不填最大数的方案数$Mx[i+1]^{S[i+1]}\ -\ (Mx[i+1]-1)^{S[i+1]}$
然后就是奇奇怪怪的离散化和预处理了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=,mo=1e9+;
int T,h,w,n,m;
int X1[N],X2[N],Y1[N],Y2[N],v[N];
int xp[N],yp[N],tx,ty,tot;
int tmp[N],t;
int f[N][N],S[N],Mx[N],P[N];
inline bool pd(int x,int y,int k) { return x>=X1[k]&&x<=X2[k]&&y>=Y1[k]&&y<=Y2[k]; }
//判断以(x,y)右上角的小块是否在矩形k中,因为离散化后小块不可能跨过矩形所以可以这样判断
inline int ksm(int x,int y)
{
int res=;
while(y)
{
if(y&) res=1ll*res*x%mo;
x=1ll*x*x%mo; y>>=;
}
return res;
}
int main()
{
//以下默认往右为大,往上为大
T=read();
while(T--)
{
memset(f,,sizeof(f)); memset(P,,sizeof(P));
xp[tx=]=; yp[ty=]=; tot=;
h=read(),w=read(),m=read(),n=read();
for(int i=;i<=n;i++)
{
X1[i]=read(),Y1[i]=read(),X2[i]=read(),Y2[i]=read(),v[i]=read();
xp[++tx]=X1[i]-,yp[++ty]=Y1[i]-;//注意-1,边界很重要,左下弄成开区间很重要!
xp[++tx]=X2[i],yp[++ty]=Y2[i];
}
xp[++tx]=h; yp[++ty]=w;
sort(xp+,xp+tx+); sort(yp+,yp+ty+);
for(int i=;i<=tx;i++) tmp[i]=xp[i]; t=tx; tx=;
for(int i=;i<=t;i++) if(i==||tmp[i]!=tmp[i-]) xp[++tx]=tmp[i];//离散化
for(int i=;i<=ty;i++) tmp[i]=yp[i]; t=ty; ty=;
for(int i=;i<=t;i++) if(i==||tmp[i]!=tmp[i-]) yp[++ty]=tmp[i];//离散化
for(int i=;i<=tx;i++)
for(int j=;j<=ty;j++)
{
tot++; Mx[tot]=m;
S[tot]=(xp[i]-xp[i-])*(yp[j]-yp[j-]);//小的边界是不包含的,即区间是左开右闭的,下开上闭的
for(int k=;k<=n;k++)
if(pd(xp[i],yp[j],k)) Mx[tot]=min(Mx[tot],v[k]);//处理Mx
for(int k=;k<=n;k++)
if(pd(xp[i],yp[j],k) && Mx[tot]==v[k])//处理P
P[tot]|=(<<k-);
}
int mx=(<<n)-; f[][]=;//DP
for(int i=;i<tot;i++)
{
int t1=ksm(Mx[i+]-,S[i+]),t2=(ksm(Mx[i+],S[i+])-t1+mo)%mo;
for(int j=;j<=mx;j++)
{
if(!f[i][j]) continue;
f[i+][j|P[i+]]=(f[i+][j|P[i+]]+1ll*f[i][j]*t2%mo)%mo;//此块填最大数
f[i+][j]=(f[i+][j]+1ll*f[i][j]*t1%mo)%mo;//此块不填最大数
}
}
printf("%d\n",f[tot][mx]);
}
}
P3813 [FJOI2017]矩阵填数的更多相关文章
- P3813 [FJOI2017]矩阵填数(组合数学)
P3813 [FJOI2017]矩阵填数 shadowice1984说:看到计数想容斥........ 这题中,我们把图分成若干块,每块的最大值域不同 蓝后根据乘法原理把每块的方案数(互不相干)相乘. ...
- [luogu P3813] [FJOI2017] 矩阵填数 解题报告 (容斥原理)
题目链接: https://www.luogu.org/problemnew/show/P3813 题目: 给定一个 h*w的矩阵,矩阵的行编号从上到下依次为 1..h,列编号从左到右依次1..w. ...
- [FJOI2017]矩阵填数——容斥
参考:题解 P3813 [[FJOI2017]矩阵填数] 题目大意: 给定一个 h∗w 的矩阵,矩阵的行编号从上到下依次为 1...h ,列编号从左到右依次 1...w . 在这个矩阵中你需要在每个格 ...
- [BZOJ5010][FJOI2017]矩阵填数(状压DP)
5010: [Fjoi2017]矩阵填数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 90 Solved: 45[Submit][Status][ ...
- bzoj5010: [Fjoi2017]矩阵填数
Description 给定一个 h*w 的矩阵,矩阵的行编号从上到下依次为 1..h,列编号从左到右依次1..w.在这个矩阵中你需要在每 个格子中填入 1..m 中的某个数.给这个矩阵填数的时候有一 ...
- bzoj 5010: [Fjoi2017]矩阵填数
Description 给定一个 h*w 的矩阵,矩阵的行编号从上到下依次为 1..h,列编号从左到右依次1..w.在这个矩阵中你需要在每 个格子中填入 1..m 中的某个数.给这个矩阵填数的时候有一 ...
- BZOJ5010 FJOI2017矩阵填数(容斥原理)
如果只考虑某个子矩阵的话,其最大值为v的方案数显然是vsize-(v-1)size.问题在于处理子矩阵间的交叉情况. 如果两个交叉的子矩阵所要求的最大值不同,可以直接把交叉部分划给所要求的最大值较小的 ...
- 【BZOJ】5010: [Fjoi2017]矩阵填数
[算法]离散化+容斥原理 [题意]给定大矩阵,可以每格都可以任意填1~m,给定n个子矩阵,要求满足子矩阵内的最大值为vi,求方案数. n<=10,h,w<=1w. [题解] 此题重点之一在 ...
- [FJOI2017]矩阵填数
[Luogu3813] [LOJ2280] 写得很好的题解 \(1.\)离散化出每一块内部不互相影响的块 \(2.\)\(dp[i][j]\)为前 \(i\) 种重叠块其中有 \(j\) 这些状态的矩 ...
随机推荐
- yii2 源码分析1从入口开始
我是在 backend 一步步打印的 很多地方我也是很模糊 .后来发现一位大神的文章(http://www.yiichina.com/tutorial/773) 参考文章自己动手开始写的 至于后来的 ...
- c++ 装饰模式(decorate)
装饰模式:动态地给一个对象添加一些额外的职责.就增加功能来说,装饰模式相比生成子类 更为灵活.有时我们希望给某个对象而不是整个类添加一些功能.比如有一个手机,允许你为手机添加特性,比如增加挂件.屏幕贴 ...
- Python 网络爬虫 010 (高级功能) 解析 robots.txt 文件
解析 robots.txt 文件 使用的系统:Windows 10 64位 Python 语言版本:Python 2.7.10 V 使用的编程 Python 的集成开发环境:PyCharm 2016 ...
- Linux nethack
一.简介 游戏目标:在地下城的最底层取得炎多的护符项链(Amulet of Yendor),并返回最上层,在圣祭坛上供奉给神灵.完成整个游戏的奖赏是,玩家会成为不朽的半神. 二.安装 1)下载源码 ...
- 1、python与ipython的下载与安装
1.ipython的下载与安装 下载链接: wget -c https://github.com/downloads/ipython/ipython/ipython-0.13.1.tar.gz ##下 ...
- 6.AND & OR 运算符
AND 和 OR 运算符用于基于一个以上的条件对记录进行过滤 AND 和 OR 运算符 AND 和 OR 可在 WHERE 子语句中把两个或多个条件结合起来. 如果第一个条件和第二个条件都成立,则 A ...
- 第八课 ROS的空间描述和变换
1.tf的实际应用 1)在机器人的配置中 从上面可以看出激光雷达中心距离机器人底座的中心有20cm,激光雷达的中心距机器人底座中心有10cm,如果激光雷达在障碍物前面0.3米,那么机器人底座离障碍物多 ...
- Requests接口测试(四)
Python序列化和反序列化 啥是序列化?啥是反序列化?这两个词听起来优点高大上的意思,其实呢不然,很简单的可以理解为: 序列化:将python的数据对象编码转换为json格式的字符串 反序列化:将j ...
- HDU 4430 Yukari's Birthday (二分)
题意:有 n 个蜡烛,让你插到蛋糕上,每一层要插 k^i个根,第0层可插可不插,插的层数是r,让 r * k 尽量小,再让 r 尽量小,求r 和 k. 析:首先先列出方程来,一个是不插的一个是插的,比 ...
- [转]不完美解决V社游戏的中文支持问题
先安装安装文泉驿正黑:sudo apt-get install fonts-wqy-zenhei 然后sudo gedit /etc/fonts/conf.avail/25-wqy-zenhei.co ...