HDU-5471 Count the Grid
题目描述
一个矩阵中可以任意填\(m\)个数。给你\(N\)个小矩阵并且告诉你此矩阵中的最大值\(v\),求有多少种大矩阵满足所给条件。\((\%1e9+7)\)
Input
包含\(T\)组数据.
第一行有\(h,w,m,n\)四个整数,接下来\(n\)行,每行包含5个整数\(x1,y1,x2,y2,v\).
表示每次选择左上角为\((x1,y1)\),右下角为\((x2,y2)\)的矩形,该矩形的最大值\(v\)。
\((T=55,1≤h,w,m≤1e4,1≤x1≤x2≤h,1≤y1≤y2≤w,1≤v≤m,1≤n≤10)\)
Output
每个样例输出Case #x: ans
Sample Input
2
3 3 2 2
1 1 2 2 2
2 2 3 3 1
4 4 4 4
1 1 2 3 3
2 3 4 4 2
2 1 4 3 2
1 2 3 4 4
Sample Output
Case #1: 28
Case #2: 76475
容斥神题!!
注意:下文中所提及的矩阵的交集必须仅包含当前的所有矩阵,即不能有其他不在当前状态的矩阵和交集有相交的地方。
我们很容易发现,题目所给出的\(n\)是十分小的,这就意味着我们可以利用状压来求解。
每个小矩阵之间的转移必定是和矩阵的交集或并集相关的,而并集很显然也要求出交集。
那么,我们就利用交集来求解。
一共有\(n\)个矩阵,那么就有\(2^n\)个交集,我们要求出这些交集的面积和最大值。
交集的最大值很好求出,直接\(min\)过去就行了。
而求交集的面积就要利用容斥了,
对于我们当前要求的集合\(s\),其集合中矩阵相交的面积为\(tot[i]\)。
我们需要去掉其他包含其他矩阵的交集的面积。
我们可以倒着枚举集合\(s\),同时枚举\(s\)是\(j\)的子集的集合\(j\)。
则集合\(s\)的交集就要减去集合\(j\)的交集。
drep(i,(1<<n)-1,0) {
tot[i]=B[i].Sum();
ret(j,i+1,1<<n)if((j|i)==j)tot[i]-=tot[j];
}
合并集合代码:
struct node {//由于要多次合并矩阵,我们可以直接将其封装起来,方便操作
int xl,yl,xr,yr,val;
inline void get(void) {
xl=Read(),yl=Read(),xr=Read(),yr=Read(),val=Read();
}
inline int Sum(void) {//求矩阵面积
return (xl>xr||yl>yr)?0:(xr-xl+1)*(yr-yl+1);
}
node operator+(node _)const {//求两的矩阵的相交矩阵
node Ans;
Ans.xl=max(xl,_.xl);
Ans.yl=max(yl,_.yl);
Ans.yr=min(yr,_.yr);
Ans.xr=min(xr,_.xr);
Ans.val=min(val,_.val);
return Ans;
}
} B[(1<<10)+5];
int main(){
B[0]=(node)<%1,1,h,w,m%>;
ret(i,1,1<<n)if((i^(i&-i)))B[i]=B[i^(i&-i)]+B[i&-i];
}
接下来,我们开始\(dp\).
定义\(dp[i][j]\)为前\(i\)种交集,已经有\(j\)状态的小矩阵满足了条件的方案数。
\(tot[i]\)为第\(i\)个交集的面积,\(val[i]\)为第\(i\)种交集的最大值,\(us[i]\)为\(i\)状态中最大值和交集最大值相同的状态。
对于当前的\(i\),我们可以对于交集是否取到最大值进行转移,
若取到了最大值,则\(dp[i][j|us[i]]+=dp[i-1][j]*(val[i]^{tot[i]}-(val[i]-1)^{tot[i]})\)。
否则,\(dp[i][j]+=dp[i-1][j]*(val[i]-1)^{tot[i]}\)。
最后答案就是\(dp[(1<<n)-1][(1<<n)-1]\)。
注意:需要利用滚动数组来优化内存
代码如下
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define reg register
#define Raed Read
#define clr(a,b) memset(a,b,sizeof a)
#define Mod(x) (x>=mod)&&(x-=mod)
#define debug(x) cerr<<#x<<" = "<<x<<endl;
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)>(b)?(b):(a))
#define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
#define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
#define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
#define erep(i,G,x) for(int i=(G).Head[x]; i; i=(G).Nxt[i])
#pragma GCC target("avx,avx2,sse4.2")
#pragma GCC optimize(3)
inline int Read(void) {
int res=0,f=1;
char c;
while(c=getchar(),c<48||c>57)if(c=='-')f=0;
do res=(res<<3)+(res<<1)+(c^48);
while(c=getchar(),c>=48&&c<=57);
return f?res:-res;
}
template<class T>inline bool Min(T &a, T const&b) {
return a>b?a=b,1:0;
}
template<class T>inline bool Max(T &a, T const&b) {
return a<b?a=b,1:0;
}
const int N=1e5+5,M=7e6+5,mod=1e9+7;
bool MOP1;
int n,dp[2][(1<<10)+5],tot[(1<<10)+5],us[(1<<10)+5];
struct node {
int xl,yl,xr,yr,val;
inline void get(void) {
xl=Read(),yl=Read(),xr=Read(),yr=Read(),val=Read();
}
inline int Sum(void) {
return (xl>xr||yl>yr)?0:(xr-xl+1)*(yr-yl+1);
}
node operator+(node _)const {
node Ans;
Ans.xl=max(xl,_.xl);
Ans.yl=max(yl,_.yl);
Ans.yr=min(yr,_.yr);
Ans.xr=min(xr,_.xr);
Ans.val=min(val,_.val);
return Ans;
}
} A[15],B[(1<<10)+5];
inline int Pow(int x,int y) {
int res=1;
while(y) {
if(y&1)res=1ll*res*x%mod;
x=1ll*x*x%mod,y>>=1;
}
return res;
}
bool MOP2;
inline void _main() {
int T=Read(),Case=0;
while(T--) {
int h=Read(),w=Read(),m=Read(),n=Read();
rep(i,1,n)A[i].get(),B[1<<(i-1)]=A[i];
B[0]=(node)<%1,1,h,w,m%>;
ret(i,1,1<<n)if((i^(i&-i)))B[i]=B[i^(i&-i)]+B[i&-i];
drep(i,(1<<n)-1,0) {
us[i]=0,tot[i]=B[i].Sum();
ret(j,i+1,1<<n)if((j|i)==j)tot[i]-=tot[j];
rep(j,1,n)if(A[j].val==B[i].val&&(i&(1<<(j-1))))us[i]|=1<<(j-1);
}
int cur=0;
clr(dp[cur],0),dp[cur][0]=1;
ret(i,0,1<<n) {
cur^=1,clr(dp[cur],0);
int res1=Pow(B[i].val-1,tot[i]);
int res2=Pow(B[i].val,tot[i]);
int _cur=!cur;
ret(j,0,1<<n)if(dp[_cur][j]) {
dp[cur][j|us[i]]+=1ll*dp[_cur][j]*((res2-res1+mod)%mod)%mod;
dp[cur][j]+=1ll*dp[_cur][j]*res1%mod;
Mod(dp[cur][j]),Mod(dp[cur][j|us[i]]);
}
}
printf("Case #%d: %d\n",++Case,dp[cur][(1<<n)-1]);
}
}
signed main() {
_main();
return 0;
}
HDU-5471 Count the Grid的更多相关文章
- HDU - 1705 Count the grid
昨天吉老师讲了皮克定理 皮克定理用于计算点阵中顶点在格点上的多边形面积.对于一个顶点全部在格点上的多边形来说,它的面积计算有如下特点: 如果用a表示位于多边形内部的格点数,b表示位于多边形边界上的格点 ...
- hdu 5471(状压DP or 容斥)
想了最复杂的思路,用了最纠结的方法,花了最长的时间,蒙了一种规律然后莫名其妙的过了. MD 我也太淼了. 后面想了下用状压好像还是挺好写的,而且复杂度也不高.推出的这个容斥的规律也没完全想透我就CAO ...
- HDU 3336 Count the string(KMP的Next数组应用+DP)
Count the string Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- hdu 4255 A Famous Grid
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4255 A Famous Grid Description Mr. B has recently dis ...
- HDU 5901 Count primes 论文题
Count primes 题目连接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5901 Description Easy question! C ...
- hdu 3336 Count the string -KMP&dp
It is well known that AekdyCoin is good at string problems as well as number theory problems. When g ...
- HDU 6470 Count 【矩阵快速幂】(广东工业大学第十四届程序设计竞赛 )
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6470 Count Time Limit: 6000/3000 MS (Java/Others) ...
- HDU 4372 Count the Buildings
Count the Buildings Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- hdu 6016 Count the Sheep(思维)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6016 题意:给定男羊和女羊的朋友关系,即给定一个图,问从任意一只羊开始连续数四只不相同的羊的方法数. ...
- hdu 5901 count prime & code vs 3223 素数密度
hdu5901题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5901 code vs 3223题目链接:http://codevs.cn/problem ...
随机推荐
- C# IIS域名绑定
C#解决IIS域名批量绑定: https://shiyousan.com/post/636022975388168065 C#程序控制IIS 添加站点域名绑定: https://blog.csdn.n ...
- 利用gephi作人物网络图
一.先利用word2vec训练数据得到模型 a.利用jieba对文本进行分词,并只提取词性为人名的词,去除分词长度为1和大于4的词 b.利用word2vec训练分词后的文本,并存储 c.利用训练后的模 ...
- MySQL数据库入门———常用基础命令
mysql 连接数据库命令: MySQL 连接本地数据库,用户名为“root”,密码“123”(注意:“-p”和“123” 之间不能有空格) mysql -h localhost -u root -p ...
- RabbitMQ消费端限流策略(十)
消费端限流: 什么是消费端限流? 场景: 我们RabbitMQ服务器有上万条未处理的消息,我们随便打开一个消费者客户端,会出现下面情况: 巨量的消息瞬间全部推送过来,但是我们单个客户端无法同时处理这么 ...
- 16.Python input()函数:获取用户输入的字符串
input() 函数用于向用户生成一条提示,然后获取用户输入的内容.由于 input() 函数总会将用户输入的内容放入字符串中,因此用户可以输入任何内容,input() 函数总是返回一个字符串. 例如 ...
- python语言中多继承中super调用所有父类的方法以及要用到的MRO顺序
在python多继承中,利用super().父类方法,可以调用所有父类,从而在重写的状态下,再次对所有父类的调用! 例: print("******多继承使用super().__init__ ...
- ZooKeeper java例子解读
转载链接:https://blog.csdn.net/liyiming2017/article/details/83276706 需求理解我们先回顾一下例子的需求,此客户端有如下四个需求: 1.它接收 ...
- oracle存储过程及sql优化-(二)
接下来比较重要,我会先贴出一个存储过程,根据这个存储过程讲解 PROCEDURE AP_CXBB_GT3_SBFGL_SBFYJSQC (OUT_RECORD OUT SYS_REFCURSOR, P ...
- LeetCode 236. 二叉树的最近公共祖先(Lowest Common Ancestor of a Binary Tree)
题目描述 给定一棵二叉树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义: “对于有根树T的两个结点u.v,最近公共祖先表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. ...
- php_network_getaddresses: getaddrinfo failed
在使用 file_get_contents远程请求url时,出现警告:php_network_getaddresses: getaddrinfo failed: Name or servicenot ...