h<=10000 * w<=10000的矩阵,每个格填不超过m<=10000的数,外加n<=10的限制,描述n个子矩阵中最大值一定要是多少,求方案数。
首先一块地能填的数就是1~这块地经过多重矩形覆盖后的最小值,然后要排除那些规定矩形填不到最大值的情况,所以答案为:每块地都满足<=该块地被限制矩形覆盖后的最小值的方案-所有一块地<该块地被限制矩形覆盖后的最小值的方案(即“某一个一定不满足条件的方案”)+所有两块地<该块地被限制矩形覆盖后的最小值的方案(即“某两个一定不满足条件的方案”)-+-+……,就是容斥。
由于要进行矩形的覆盖并且统计每个数据出现的次数来计算答案,就把坐标离散化一波,并把离散化后切成的每一块矩形的面积处理出来。为了方便,把按离散化后坐标切成的矩形标记为左开右闭(或左闭右开)。
1 #include2 #include 3 #include 4 #include 5 //#include 6 using namespace std; 7 8 int h,w,m,n; 9 int xx[23],yy[23],vv[23],lx=0,ly=0,lv=0;10 struct mat{ int x1,x2,y1,y2,v;}a[23];11 const int mod=1e9+7;12 int mp[23][23],re[23][23],cnt[23];13 int powmod(int a,int b)14 {15 int ans=1,tmp=a;16 while (b) { if (b&1) ans=1ll*ans*tmp%mod;tmp=1ll*tmp*tmp%mod;b>>=1;}17 return ans;18 }19 int t;20 int main()21 {22 scanf("%d",&t);23 while (t--)24 {25 scanf("%d%d%d%d",&h,&w,&m,&n);26 xx[lx=1]=0;xx[lx=2]=h;27 yy[ly=1]=0;yy[ly=2]=w;28 vv[lv=1]=m;29 for (int i=1;i<=n;i++)30 {31 scanf("%d%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2,&a[i].v);32 a[i].x1--;a[i].y1--;33 xx[++lx]=a[i].x1;xx[++lx]=a[i].x2;34 yy[++ly]=a[i].y1;yy[++ly]=a[i].y2;35 vv[++lv]=a[i].v;vv[++lv]=a[i].v-1;36 }37 sort(xx+1,xx+1+lx);sort(yy+1,yy+1+ly);sort(vv+1,vv+1+lv);38 lx=unique(xx+1,xx+1+lx)-xx-1;ly=unique(yy+1,yy+1+ly)-yy-1;lv=unique(vv+1,vv+1+lv)-vv-1;39 for (int i=1;i<=lx;i++)40 for (int j=1;j<=ly;j++)41 re[i][j]=(xx[i]-xx[i-1])*(yy[j]-yy[j-1]);42 for (int i=1;i<=n;i++)43 {44 a[i].x1=lower_bound(xx+1,xx+1+lx,a[i].x1)-xx;45 a[i].y1=lower_bound(yy+1,yy+1+ly,a[i].y1)-yy;46 a[i].x2=lower_bound(xx+1,xx+1+lx,a[i].x2)-xx;47 a[i].y2=lower_bound(yy+1,yy+1+ly,a[i].y2)-yy;48 a[i].v=lower_bound(vv+1,vv+1+lv,a[i].v)-vv;49 }50 int ans=0;51 for (int s=0;s<(1< >(i-1))&1) now=-now,v--;61 for (int j=a[i].x1+1;j<=a[i].x2;j++)62 for (int k=a[i].y1+1;k<=a[i].y2;k++)63 mp[j][k]=min(mp[j][k],v);64 }65 memset(cnt,0,sizeof(cnt));66 for (int i=1;i<=lx;i++)67 for (int j=1;j<=ly;j++)68 cnt[mp[i][j]]+=re[i][j];69 for (int i=1;i<=lv;i++) if (cnt[i]) now=1ll*now*powmod(vv[i],cnt[i])%mod;70 ans=(ans+now)%mod;71 }72 printf("%d\n",(ans+mod)%mod);73 }74 return 0;75 }76