LGP3813题解

这道题是我去年11月份的时候看到的,当时写了一个假的做法没过样例,然后就没管了。

结果今天在模拟赛的时候放到了 T1(

我也不知道他为什么是对的,可是他就是过了样例和大样例.jpg

容易发现 \(n\) 个矩形的边,将整个矩形划分成了 \((2n)^2\) 个小矩形。这样方便对每个小矩形考虑。

发现一个矩形的限制相当于限制了一车矩形的最大值,所以我们可以做一个 \(O(n^3)\) 的暴力得到每个小矩形的最大值是多少。

我们将最大值限制相同的小矩阵拉出来一起考虑。同时把限制为这个值的 \(O(n)\) 个矩阵拉出来。

看到数据范围 \(n=10\),考虑对这些限制值的矩阵容斥。

\(f[S]\) 为选取的矩阵的最大值不为 \(v\) 的方案,那么其他矩阵可以随便乱放。

这一部分的答案就是 \(\sum(-1)^{|S|}f[S]\),而 \(f[S]\) 跑一个暴力是很容易计算的。

我们就做到了 \(O(n^32^n)\),并且还跑不满(

//我也不知道他为什么是对的,可是他就是过了样例和大样例
#include<algorithm>
#include<cstdio>
const int M=15,mod=1e9+7;
int n,V,x,y,lx,ly,len,ppc[1<<M],tx[M<<1],ty[M<<1],mx[M<<1][M<<1];
bool vis[M<<1][M<<1];
struct mat{
	int l1,l2,r1,r2,v;//(l1,r1]*(l2,r2]
	inline bool operator<(const mat&it)const{
		return v<it.v;
	}
}m[M],t[M];
inline int pow(int a,int b=mod-2){
	int ans(1);for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;
}
inline int min(const int&a,const int&b){
	return a>b?b:a;
}
inline int Solve(const int&v){
	int ans(0),sum(0);
	for(int i=2;i<=lx;++i)for(int j=2;j<=ly;++j){
		if(mx[i][j]==v)sum+=(tx[i]-tx[i-1])*(ty[j]-ty[j-1]);
	}
	for(int S=0;S<(1<<len);++S){
		int cnt(0);
		for(int i=0;i<len;++i)if(S>>i&1){
			for(int x=t[i+1].l1+1;x<=t[i+1].r1;++x){
				for(int y=t[i+1].l2+1;y<=t[i+1].r2;++y){
					if(mx[x][y]==v&&!vis[x][y])cnt+=(tx[x]-tx[x-1])*(ty[y]-ty[y-1]),vis[x][y]=true;
				}
			}
		}
		for(int i=2;i<=lx;++i)for(int j=2;j<=ly;++j)vis[i][j]=false;
		if(ppc[S]&1)ans=(ans+1ll*(mod-pow(v-1,cnt))*pow(v,sum-cnt))%mod;
		else ans=(ans+1ll*pow(v-1,cnt)*pow(v,sum-cnt))%mod;
	}
	return ans;
}
signed main(){
	freopen("matrix.in","r",stdin);
	freopen("matrix.out","w",stdout);
	int T;scanf("%d",&T);
	for(int i=1;i<1024;++i)ppc[i]=ppc[i>>1]+(i&1);
	while(T--){
		int ans(1);
		scanf("%d%d%d%d",&x,&y,&V,&n);lx=ly=0;
		tx[++lx]=0;tx[++lx]=x;ty[++ly]=0;ty[++ly]=y;
		for(int i=1;i<=n;++i){
			scanf("%d%d%d%d%d",&m[i].l1,&m[i].l2,&m[i].r1,&m[i].r2,&m[i].v);
			--m[i].l1;tx[++lx]=m[i].l1;tx[++lx]=m[i].r1;
			--m[i].l2;ty[++ly]=m[i].l2;ty[++ly]=m[i].r2;
		}
		std::sort(m+1,m+n+1);
		std::sort(tx+1,tx+lx+1);lx=std::unique(tx+1,tx+lx+1)-tx-1;
		std::sort(ty+1,ty+ly+1);ly=std::unique(ty+1,ty+ly+1)-ty-1;
		for(int i=1;i<=n;++i){
			m[i].l1=std::lower_bound(tx+1,tx+lx+1,m[i].l1)-tx;
			m[i].r1=std::lower_bound(tx+1,tx+lx+1,m[i].r1)-tx;
			m[i].l2=std::lower_bound(ty+1,ty+ly+1,m[i].l2)-ty;
			m[i].r2=std::lower_bound(ty+1,ty+ly+1,m[i].r2)-ty;
		}
		for(int i=2;i<=lx;++i)for(int j=2;j<=ly;++j)mx[i][j]=0x7fffffff;
		for(int id=1;id<=n;++id){
			for(int i=m[id].l1+1;i<=m[id].r1;++i){
				for(int j=m[id].l2+1;j<=m[id].r2;++j){
					mx[i][j]=min(mx[i][j],m[id].v);
				}
			}
		}
		for(int i=1;i<=n;++i){
			if(i!=1&&m[i].v!=m[i-1].v)ans=1ll*ans*Solve(m[i-1].v)%mod,len=0;t[++len]=m[i];
		}
		ans=1ll*ans*Solve(m[n].v)%mod;len=0;
		for(int i=2;i<=lx;++i)for(int j=2;j<=ly;++j){
			if(mx[i][j]==0x7fffffff)ans=1ll*ans*pow(V,(tx[i]-tx[i-1])*(ty[j]-ty[j-1]))%mod;
		}
		printf("%d\n",ans);
	}
}
posted @ 2022-03-05 16:21  Prean  阅读(19)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};