想了最复杂的思路,用了最纠结的方法,花了最长的时间,蒙了一种规律然后莫名其妙的过了。

MD 我也太淼了。

后面想了下用状压好像还是挺好写的,而且复杂度也不高。推出的这个容斥的规律也没完全想透我就CAO。

Count the Grid

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 400    Accepted Submission(s): 86

Problem Description
You get a grid of h rows and w columns. Rows are numbered 1, 2, 3, ... , h from top to bottom while columns are numbered 1, 2 , 3, ... , w from left to right. Each cell can be represented by a pair of numbers (x, y), which means this cell is located at row x column y.
You fill the every cell with an integer ranging from 1 to m.
Then you start to play with the gird. Every time you chose a rectangle whose upper left cell is (x1, y1) and lower right cell is (x2, y2), finally you calculate the maximum value v of this rectangle.
After you played n times, you left. When you return, you find that the grid is disappeared. You only remember n rectangles and their corresponding maximum value. You are wondering how many different gird can satisfy your memory. Two grids are different if there is a cell filled different integer.
Give your answer modulo (109+7).
Your memory may have some mistakes so that no grid satisfies it, in this case just output 0.
 
Input
Multiple test cases. In the first line there is an integer T, indicating the number of test cases. For each test case. First line contain 4 integers h, w, m, n. Next are n lines, each line contain 5 integers x1, y1, x2, y2, v.
(T=55,1≤h,w,m≤104,1≤x1≤x2≤h,1≤y1≤y2≤w,1≤v≤m,1≤n≤10, there are i test cases for n = i)
 
Output
For each test case, please output one line. The output format is "Case #x: ans", x is the case number, starting from 1.
 
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
 
Source
 
Recommend
hujie   |   We have carefully selected several similar problems for you:  5493 5492 5491 5490 5489 
 
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <math.h>
using namespace std;
#define MOD 1000000007 int h,w,m,n;
struct node
{
int x1,y1,x2,y2;
int num;
int areacnt;
int area[];//记录其中的小区域
}g[],tg[]; struct Rect
{
int x1,y1,x2,y2;
}rect[]; bool flag_noans;
int tmpsaverect[];
int tmprectcnt; long long savemul[];
bool saverectinarea[][];
bool flagrect[];
bool flagarea[];
bool flagg[];
int x[],y[];
long long ans;
long long tmpans;
long long ansans; bool cmpgnum(node tl,node tr)
{
return tl.num<tr.num;
} bool checkareabelong(int rectpoint,int gi)
{
if(g[gi].x1<=rect[rectpoint].x1&&g[gi].y1<=rect[rectpoint].y1 && g[gi].x2>=rect[rectpoint].x2&&g[gi].y2>=rect[rectpoint].y2 )
{
return ;
}
return ;
} int getrectareanum(int i)
{
return (rect[i].y2-rect[i].y1+)*(rect[i].x2-rect[i].x1+);
} long long quick_pow(int aa,int bb)//a^b
{
long long ans_pow=;
long long tmp_pow=aa;
while(bb)
{
if(bb&)
ans_pow = (ans_pow*tmp_pow)%MOD;
tmp_pow = (tmp_pow*tmp_pow)%MOD;
bb>>=;
}
return ans_pow;
} long long cnt_bigoneism(int allnum,int bigm)
{
return ((quick_pow(bigm,allnum)-quick_pow(bigm-,allnum))%MOD+MOD)%MOD;
} void dfs(int s,int ends,int cnt_nowhave,int tmp_m)
{
//明显错了
if(cnt_nowhave!=)
{
int cnt_inarea=;
int cnt_outarea=;
for(int i=;i<tmprectcnt;i++)
{
int tmp_flag=;
for(int j=;j<ends;j++)
{
if(flagarea[j]==true)
{
if( saverectinarea[i][j]==true )
{
tmp_flag=;
cnt_inarea += getrectareanum( tmpsaverect[i] );
break;
} /*
if( tg[j].x1<=rect[tmpsaverect[i]].x1&&tg[j].y1<=rect[tmpsaverect[i]].y1&& tg[j].x2>=rect[tmpsaverect[i]].x2&&tg[j].y2>=rect[tmpsaverect[i]].y2 )
{
tmp_flag=1;
cnt_inarea += getrectareanum( tmpsaverect[i] );
break;
}
*/
}
}
if(tmp_flag==)
{
cnt_outarea += getrectareanum( tmpsaverect[i] );
} }
if( !(cnt_outarea==||cnt_inarea==) )
{
long long tmp_sum = ( quick_pow(tmp_m-,cnt_inarea)*cnt_bigoneism(cnt_outarea,tmp_m) )%MOD;
ansans = (ansans+savemul[cnt_nowhave]*tmp_sum)%MOD;
}
}
for(int i=s;i<ends;i++)
{
flagarea[i]=true;
dfs(i+,ends,cnt_nowhave+,tmp_m);
flagarea[i]=false;
}
} long long get_numtime(int mxt,int tm)
{
//有t个不满足的情况
memset(flagarea,false,sizeof(flagarea));
ansans=;
dfs(,mxt,,tm);
return ansans;
} int main()
{
int T;
int tt=;
scanf("%d",&T);
//设计模式还是很成问题。
while(T--)
{
flag_noans=false;
scanf("%d%d%d%d",&h,&w,&m,&n);
for(int i=;i<n;i++)
{
int x1,y1,x2,y2,tmp;
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&tmp);
x[*i]=x1;
x[*i+]=x2+;
y[*i]=y1;
y[*i+]=y2+; g[i].x1=x1;g[i].y1=y1;
g[i].x2=x2;g[i].y2=y2;
g[i].num=tmp;
g[i].areacnt=;
}
x[*n]=;
x[*n+]=h+;
y[*n]=;
y[*n+]=w+;
int id=;//用来标记最小矩形
sort(x,x+*(n+));
sort(y,y+*(n+));
int prex=;
for(int i=;i<*(n+);i++)
{
if(x[i]==prex) continue;
int prey=;
for(int j=;j<*(n+);j++)
{
if(y[j]==prey) continue;
rect[id].x1=prex;
rect[id].y1=prey;
rect[id].x2=x[i]-;
rect[id].y2=y[j]-;
prey=y[j];
id++;
}
prex=x[i];
} for(int i=;i<id;i++)
{
for(int j=;j<n;j++)
{
if( checkareabelong(i,j) == true )
{
g[j].area[ g[j].areacnt ]=i;
g[j].areacnt++;
}
}
} //然后就是容斥原理了 int cntother=;//统计有多少个格子是完全没有拘束的
for(int i=;i<id;i++)
{
bool signareain=;
for(int j=;j<n;j++)
{
if( checkareabelong(i,j)==true )
{
signareain=true;
break;
}
}
if(signareain == false)
{
cntother += getrectareanum(i);
}
}
ans=quick_pow(m,cntother);
sort(g,g+n,cmpgnum);
memset(flagrect,false,sizeof(flagrect));
for(int i=;i<n;i++)
{
int ti;
for(ti=i;ti<n;ti++)
{
if( g[ti].num != g[i].num ) break;
tg[ti-i]=g[ti];
}
int cntcnt=;//用来判断不满足条件的情况
memset(flagg,,sizeof(flagg));
ti--;
//[i,ti] have the same .num
tmprectcnt=;
int tmpcntnum=;
for(int j=;j<id;j++)
{
if( flagrect[j]==true ) continue;//已经计数过的,不需要
for(int gi=i;gi<=ti;gi++)
if( checkareabelong(j,gi)==true )
{
flagrect[j]=true;
tmpsaverect[tmprectcnt]=j;
tmpcntnum += getrectareanum(j);
tmprectcnt++;
break;
}
for(int gi=i;gi<=ti;gi++)
{
if( checkareabelong(j,gi)==true )
{
if(flagg[gi]==)
{
flagg[gi]=;
cntcnt++;
}
}
}
} //容斥原理开始
if(tmprectcnt==||cntcnt!=ti-i+)
{
flag_noans=true;
break;
} for(int j=;j<tmprectcnt;j++)
for(int j1=;j1<ti-i+;j1++)
{
if( tg[j1].x1<=rect[tmpsaverect[j]].x1&&tg[j1].y1<=rect[tmpsaverect[j]].y1&& tg[j1].x2>=rect[tmpsaverect[j]].x2&&tg[j1].y2>=rect[tmpsaverect[j]].y2 )
{
saverectinarea[j][j1]=true;
}
else saverectinarea[j][j1]=false;
} tmpans = cnt_bigoneism(tmpcntnum,g[i].num);// 总的个数
int flag_sign = -;
long long num_mul=;
for(int j=;j<=ti-i;j++)
{
savemul[j]=flag_sign*num_mul;
//tmpans = tmpans + flag_sign*num_mul*get_numtime(j,ti-i+1,g[i].num);//j个不满足的情况
//tmpans = (tmpans%MOD+MOD)%MOD;
flag_sign *= -;
//num_mul=(num_mul*(j+1))%MOD; }
get_numtime(ti-i+,g[i].num);
tmpans = tmpans + ansans;
ans = (ans*tmpans)%MOD;
i=ti;//这一步一直忘了
}
printf("Case #%d: ",tt++);
if(flag_noans==true)
cout<<<<endl;
else cout<<(ans%MOD+MOD)%MOD<<endl;
}
return ;
}

hdu 5471(状压DP or 容斥)的更多相关文章

  1. UOJ #129 / BZOJ 4197 / 洛谷 P2150 - [NOI2015]寿司晚宴 (状压dp+数论+容斥)

    题面传送门 题意: 你有一个集合 \(S={2,3,\dots,n}\) 你要选择两个集合 \(A\) 和 \(B\),满足: \(A \subseteq S\),\(B \subseteq S\), ...

  2. 【HDOJ5519】Kykneion asma(状压DP,容斥)

    题意:给定n和a[i](i=0..4),求所有n位5进制数中没有前导0且i出现的次数不超过a[i]的数的个数 2<=n<=15000,0<=a[i]<=3e4 思路:设f(n, ...

  3. bzoj4036 [HAOI2015]按位或 状压DP + MinMax 容斥

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4036 题解 变成 \(2^n-1\) 的意思显然就是每一个数位都出现了. 那么通过 MinMa ...

  4. 2019.02.09 bzoj2560: 串珠子(状压dp+简单容斥)

    传送门 题意简述:nnn个点的带边权无向图,定义一个图的权值是所有边的积,问所有nnn个点都连通的子图的权值之和. 思路: fif_ifi​表示保证集合iii中所有点都连通其余点随意的方案数. gig ...

  5. HDU 4778 状压DP

    一看就是状压,由于是类似博弈的游戏.游戏里的两人都是绝对聪明,那么先手的选择是能够确定最终局面的. 实际上是枚举最终局面情况,0代表是被Bob拿走的,1为Alice拿走的,当时Alice拿走且满足变换 ...

  6. HDU 3001 状压DP

    有道状压题用了搜索被队友骂还能不能好好训练了,, hdu 3001 经典的状压dp 大概题意..有n个城市 m个道路  成了一个有向图.n<=10: 然后这个人想去旅行.有个超人开始可以把他扔到 ...

  7. hdu 2809(状压dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2809 思路:简单的状压dp,看代码会更明白. #include<iostream> #in ...

  8. hdu 2167(状压dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2167 思路:经典的状压dp题,前后,上下,对角8个位置不能取,状态压缩枚举即可所有情况,递推关系是为d ...

  9. Engineer Assignment HDU - 6006 状压dp

    http://acm.split.hdu.edu.cn/showproblem.php?pid=6006 比赛的时候写了一个暴力,存暴力,过了,还46ms 那个暴力的思路是,预处理can[i][j]表 ...

随机推荐

  1. System.getProperty("line.separator")

    转自:http://blog.sina.com.cn/s/blog_707577700100nv74.html 标题所写的代码能获得当前系统的换行符. 不要随便用 \n\r    \n    \r,因 ...

  2. 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-人机界面快速入门 TC2

    创建最简单的静态文本,就像是label,就只需要绘制一个矩形框,然后填写Text,取消边框即可(你也可以设置自定义字体)   创建动态的文本框,就像是textbox,需要设置这个矩形框的Text为%d ...

  3. UGUI 实现界面 渐隐渐现 FadeIn/Out 效果

    孙广东  2015.7.10 事实上熟悉NGUI的人,应该知道  实现渐隐渐现 FadeIn/Out 效果是非常方便的,由于父对象 的 改变会自己主动影响到子对象. 比方 UIWidget.UIPan ...

  4. 对象内部属性[[Class]]

    1.概述 所有的typeof返回值为‘object’的对象都包含一个内部属性[[Class]],我们将它可以看做内部的分类,而非传统面向对象意义的分类.这个属性无法直接访问,一般通过Object.pr ...

  5. C++中的INL(转)

    inl 文件是内联函数的源文件. 内联函数通常在c++头文件中实现,但有的时候内联函数较多或者出于一些别的考虑(使头文件看起来更简洁等), 往往会将这部分具体定义的代码添加到INL文件中,然后在该头文 ...

  6. Kubernetes使用prometheus+grafana做一个简单的监控方案

    前言 本文介绍在k8s集群中使用node-exporter.prometheus.grafana对集群进行监控.其实现原理有点类似ELK.EFK组合.node-exporter组件负责收集节点上的me ...

  7. sshd服务安装和配置管理

    1.SSHD简介(介绍) SSH协议:安全外壳协议,为Secure Shell的缩写,SSH为建立在应用层和传输层基础上的安全协议. sshd服务使用SSH协议可以用来进行远程控制,或在计算机之间传送 ...

  8. C++语言基础(15)-友元函数和友元类

    一个类中可以有 public.protected.private 三种属性的成员,通过对象可以访问 public 成员,只有本类中的函数可以访问本类的 private 成员.现在,我们来介绍一种例外情 ...

  9. Java 十进制和十六制之间的转化(负数的处理)

    原文: http://www.cnblogs.com/literoad/archive/2013/01/25/2875908.html 在一些情况下,我们需要将数字在十进制和十六制下互相转化. 在Ja ...

  10. oracle如何将数据导入到另一个表空间

    某个用户的数据在USER表空间里,如果多个用户的数据都在USERS表空间内,将严重影响系统性能,一般在系统迁移的时候,在新的系统里希望导入 一个独立的用户表空间,但是经常无法导入用户指定的缺省表空间, ...