题目描述

一个矩阵中可以任意填\(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

  1. 2
  2. 3 3 2 2
  3. 1 1 2 2 2
  4. 2 2 3 3 1
  5. 4 4 4 4
  6. 1 1 2 3 3
  7. 2 3 4 4 2
  8. 2 1 4 3 2
  9. 1 2 3 4 4

Sample Output

  1. Case #1: 28
  2. Case #2: 76475

容斥神题!!

注意:下文中所提及的矩阵的交集必须仅包含当前的所有矩阵,即不能有其他不在当前状态的矩阵和交集有相交的地方。

我们很容易发现,题目所给出的\(n\)是十分小的,这就意味着我们可以利用状压来求解。

每个小矩阵之间的转移必定是和矩阵的交集或并集相关的,而并集很显然也要求出交集。

那么,我们就利用交集来求解。

一共有\(n\)个矩阵,那么就有\(2^n\)个交集,我们要求出这些交集的面积和最大值。

交集的最大值很好求出,直接\(min\)过去就行了。

而求交集的面积就要利用容斥了,


对于我们当前要求的集合\(s\),其集合中矩阵相交的面积为\(tot[i]\)。

我们需要去掉其他包含其他矩阵的交集的面积。

我们可以倒着枚举集合\(s\),同时枚举\(s\)是\(j\)的子集的集合\(j\)。

则集合\(s\)的交集就要减去集合\(j\)的交集。

  1. drep(i,(1<<n)-1,0) {
  2. tot[i]=B[i].Sum();
  3. ret(j,i+1,1<<n)if((j|i)==j)tot[i]-=tot[j];
  4. }

合并集合代码:


  1. struct node {//由于要多次合并矩阵,我们可以直接将其封装起来,方便操作
  2. int xl,yl,xr,yr,val;
  3. inline void get(void) {
  4. xl=Read(),yl=Read(),xr=Read(),yr=Read(),val=Read();
  5. }
  6. inline int Sum(void) {//求矩阵面积
  7. return (xl>xr||yl>yr)?0:(xr-xl+1)*(yr-yl+1);
  8. }
  9. node operator+(node _)const {//求两的矩阵的相交矩阵
  10. node Ans;
  11. Ans.xl=max(xl,_.xl);
  12. Ans.yl=max(yl,_.yl);
  13. Ans.yr=min(yr,_.yr);
  14. Ans.xr=min(xr,_.xr);
  15. Ans.val=min(val,_.val);
  16. return Ans;
  17. }
  18. } B[(1<<10)+5];
  19. int main(){
  20. B[0]=(node)<%1,1,h,w,m%>;
  21. ret(i,1,1<<n)if((i^(i&-i)))B[i]=B[i^(i&-i)]+B[i&-i];
  22. }

接下来,我们开始\(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]\)。

注意:需要利用滚动数组来优化内存

代码如下

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define LL long long
  4. #define reg register
  5. #define Raed Read
  6. #define clr(a,b) memset(a,b,sizeof a)
  7. #define Mod(x) (x>=mod)&&(x-=mod)
  8. #define debug(x) cerr<<#x<<" = "<<x<<endl;
  9. #define max(a,b) ((a)>(b)?(a):(b))
  10. #define min(a,b) ((a)>(b)?(b):(a))
  11. #define rep(a,b,c) for(reg int a=(b),a##_end_=(c); a<=a##_end_; ++a)
  12. #define ret(a,b,c) for(reg int a=(b),a##_end_=(c); a<a##_end_; ++a)
  13. #define drep(a,b,c) for(reg int a=(b),a##_end_=(c); a>=a##_end_; --a)
  14. #define erep(i,G,x) for(int i=(G).Head[x]; i; i=(G).Nxt[i])
  15. #pragma GCC target("avx,avx2,sse4.2")
  16. #pragma GCC optimize(3)
  17. inline int Read(void) {
  18. int res=0,f=1;
  19. char c;
  20. while(c=getchar(),c<48||c>57)if(c=='-')f=0;
  21. do res=(res<<3)+(res<<1)+(c^48);
  22. while(c=getchar(),c>=48&&c<=57);
  23. return f?res:-res;
  24. }
  25. template<class T>inline bool Min(T &a, T const&b) {
  26. return a>b?a=b,1:0;
  27. }
  28. template<class T>inline bool Max(T &a, T const&b) {
  29. return a<b?a=b,1:0;
  30. }
  31. const int N=1e5+5,M=7e6+5,mod=1e9+7;
  32. bool MOP1;
  33. int n,dp[2][(1<<10)+5],tot[(1<<10)+5],us[(1<<10)+5];
  34. struct node {
  35. int xl,yl,xr,yr,val;
  36. inline void get(void) {
  37. xl=Read(),yl=Read(),xr=Read(),yr=Read(),val=Read();
  38. }
  39. inline int Sum(void) {
  40. return (xl>xr||yl>yr)?0:(xr-xl+1)*(yr-yl+1);
  41. }
  42. node operator+(node _)const {
  43. node Ans;
  44. Ans.xl=max(xl,_.xl);
  45. Ans.yl=max(yl,_.yl);
  46. Ans.yr=min(yr,_.yr);
  47. Ans.xr=min(xr,_.xr);
  48. Ans.val=min(val,_.val);
  49. return Ans;
  50. }
  51. } A[15],B[(1<<10)+5];
  52. inline int Pow(int x,int y) {
  53. int res=1;
  54. while(y) {
  55. if(y&1)res=1ll*res*x%mod;
  56. x=1ll*x*x%mod,y>>=1;
  57. }
  58. return res;
  59. }
  60. bool MOP2;
  61. inline void _main() {
  62. int T=Read(),Case=0;
  63. while(T--) {
  64. int h=Read(),w=Read(),m=Read(),n=Read();
  65. rep(i,1,n)A[i].get(),B[1<<(i-1)]=A[i];
  66. B[0]=(node)<%1,1,h,w,m%>;
  67. ret(i,1,1<<n)if((i^(i&-i)))B[i]=B[i^(i&-i)]+B[i&-i];
  68. drep(i,(1<<n)-1,0) {
  69. us[i]=0,tot[i]=B[i].Sum();
  70. ret(j,i+1,1<<n)if((j|i)==j)tot[i]-=tot[j];
  71. rep(j,1,n)if(A[j].val==B[i].val&&(i&(1<<(j-1))))us[i]|=1<<(j-1);
  72. }
  73. int cur=0;
  74. clr(dp[cur],0),dp[cur][0]=1;
  75. ret(i,0,1<<n) {
  76. cur^=1,clr(dp[cur],0);
  77. int res1=Pow(B[i].val-1,tot[i]);
  78. int res2=Pow(B[i].val,tot[i]);
  79. int _cur=!cur;
  80. ret(j,0,1<<n)if(dp[_cur][j]) {
  81. dp[cur][j|us[i]]+=1ll*dp[_cur][j]*((res2-res1+mod)%mod)%mod;
  82. dp[cur][j]+=1ll*dp[_cur][j]*res1%mod;
  83. Mod(dp[cur][j]),Mod(dp[cur][j|us[i]]);
  84. }
  85. }
  86. printf("Case #%d: %d\n",++Case,dp[cur][(1<<n)-1]);
  87. }
  88. }
  89. signed main() {
  90. _main();
  91. return 0;
  92. }

HDU-5471 Count the Grid的更多相关文章

  1. HDU - 1705 Count the grid

    昨天吉老师讲了皮克定理 皮克定理用于计算点阵中顶点在格点上的多边形面积.对于一个顶点全部在格点上的多边形来说,它的面积计算有如下特点: 如果用a表示位于多边形内部的格点数,b表示位于多边形边界上的格点 ...

  2. hdu 5471(状压DP or 容斥)

    想了最复杂的思路,用了最纠结的方法,花了最长的时间,蒙了一种规律然后莫名其妙的过了. MD 我也太淼了. 后面想了下用状压好像还是挺好写的,而且复杂度也不高.推出的这个容斥的规律也没完全想透我就CAO ...

  3. 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) ...

  4. hdu 4255 A Famous Grid

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4255 A Famous Grid Description Mr. B has recently dis ...

  5. HDU 5901 Count primes 论文题

    Count primes 题目连接: http://acm.split.hdu.edu.cn/showproblem.php?pid=5901 Description Easy question! C ...

  6. 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 ...

  7. HDU 6470 Count 【矩阵快速幂】(广东工业大学第十四届程序设计竞赛 )

    题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6470 Count Time Limit: 6000/3000 MS (Java/Others)    ...

  8. HDU 4372 Count the Buildings

    Count the Buildings Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  9. hdu 6016 Count the Sheep(思维)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6016 题意:给定男羊和女羊的朋友关系,即给定一个图,问从任意一只羊开始连续数四只不相同的羊的方法数. ...

  10. hdu 5901 count prime & code vs 3223 素数密度

    hdu5901题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5901 code vs 3223题目链接:http://codevs.cn/problem ...

随机推荐

  1. C语言 - strcat和strncat的编程实现及总结

    一.函数strcat与stcncat的函数实现 1.strcat函数的实现 要求: 原型:char * strcat(char *dest, const char *src);    头文件:#inc ...

  2. 窗体操作:ShowWindow(SW_HIDE)

    BOOL ShowWindow( int nCmdShow ); Return Value 作用: 如果窗口原来可见,则返回非零值:如果CWnd原来是隐藏的,则返回0   参数: Parameters ...

  3. [CF666E]Forensic Examination:后缀自动机+线段树合并

    分析 用到了两个小套路: 使用线段树合并维护广义后缀自动机的\(right\)集合. 查询\(S[L,R]\)在\(T\)中的出现次数:给\(T\)建SAM,在上面跑\(S\),跑到\(R\)的时候先 ...

  4. [pytorch笔记] torch.nn vs torch.nn.functional; model.eval() vs torch.no_grad(); nn.Sequential() vs nn.moduleList

    1. torch.nn与torch.nn.functional之间的区别和联系 https://blog.csdn.net/GZHermit/article/details/78730856 nn和n ...

  5. 安装破解confluence6.7.1(插图丢了,一直懒得补)

      JIRA安装:https://www.cnblogs.com/wei9593/p/10194784.html 1环境: centos7.2 java-1.8https://www.cnblogs. ...

  6. EDA cheat sheet

    %config InlineBackend.figure_format = 'svg' 在jupyter notebook中使用这个命令绘制更清晰的图像,注意百分号后不能有空格. 1. Univari ...

  7. C++入门经典-例4.11-名称空间的定义和使用

    1:名称空间,也成为名字空间.命名空间,关键字为namespace.我们经常使用这样一条语句: using namespace std: 我们要使用标准输入输出流,除了包含它们所在的头文件外,还必须使 ...

  8. 十四周学习总结&简易记事本

    学习总结: 一.JDBC: 1.JDBC提供里一套与平台无关的标准数据库操作接口和类,只要支持java的数据库厂商,所提供的数据库都可以以使用JDBC操作. 2.JDBC的主要操作类及接口: 3.JD ...

  9. 黑马lavarel教程---8、session

    黑马lavarel教程---8.session 一.总结 一句话总结: 1.session默认保存在文件中 2.使用的话通过Session门面或者辅助函数 1.lavarel中session的保存方式 ...

  10. spark MLlib 概念 1:相关系数( PPMCC or PCC or Pearson's r皮尔森相关系数) and Spearman's correlation(史匹曼等级相关系数)

    皮尔森相关系数定义: 协方差与标准差乘积的商. Pearson's correlation coefficient when applied to a population is commonly r ...