题解:P3813 [FJOI2017] 矩阵填数
思路
我们分析发现子矩阵之间的相互影响很重要,也不好处理。但是注意到权值小的子矩阵填完后一定不会影响权值大的子矩阵的答案。
于是考虑按照值域从小到大依次考虑每一个权值方案,做乘法原理即可。
问题转化为相同权值的一些子矩阵,满足每一个子矩阵的值不超过
我们钦定一些矩阵不存在权值为
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
int T;
int H,W,n,m;
struct Matrix{
int lx,ly,rx,ry,v;
}Mat[15];
bool cmp(Matrix aa,Matrix bb){
return aa.v<bb.v;
}
int x[35],y[35];
int siz[55][55];
int lim[55][55];
bool vis[55][55];
int qp(int x,int p){
int res=1;
while(p){
if(p&1)res=res*x%mod;
x=x*x%mod;
p>>=1;
}
return res;
}
vector<int>vec;
int tot1,tot2;
int solve(int V,int sum){
int num=vec.size();
int ans=0;
for(int S=0;S<(1<<num);S++){
int ct=0;
int k=__builtin_popcount(S);
for(int px=1;px<tot1;px++){
for(int py=1;py<tot2;py++){
if(lim[px][py]!=V)continue;
for(int i=0;i<num;i++){
if((1<<i)&S){
if(px>=Mat[vec[i]].lx&&px<Mat[vec[i]].rx&&py>=Mat[vec[i]].ly&&py<Mat[vec[i]].ry){
ct+=siz[px][py];
break;
}
}
}
}
}
int res=qp(V-1,ct)*qp(V,sum-ct)%mod;
if(k&1)ans=(ans-res+mod)%mod;
else ans=(ans+res)%mod;
}
return ans;
}
signed main(){
cin>>T;
while(T--){
memset(vis,0,sizeof(vis));
memset(lim,0,sizeof(lim));
memset(siz,0,sizeof(siz));
cin>>H>>W>>m>>n;
for(int i=1;i<=n;i++){
int lx,ly,rx,ry,v;
cin>>lx>>ly>>rx>>ry>>v;
x[i]=lx,x[i+n]=rx+1;
y[i]=ly,y[i+n]=ry+1;
Mat[i]={lx,ly,rx+1,ry+1,v};
}
sort(x+1,x+1+n*2);
sort(y+1,y+1+n*2);
tot1=unique(x+1,x+1+n*2)-x-1;
tot2=unique(y+1,y+1+n*2)-y-1;
sort(Mat+1,Mat+n+1,cmp);
for(int i=1;i<=n;i++){
Mat[i].lx=lower_bound(x+1,x+1+tot1,Mat[i].lx)-x;
Mat[i].ly=lower_bound(y+1,y+1+tot2,Mat[i].ly)-y;
Mat[i].rx=lower_bound(x+1,x+1+tot1,Mat[i].rx)-x;
Mat[i].ry=lower_bound(y+1,y+1+tot2,Mat[i].ry)-y;
}
int cnt=0,ans=1;
int num=H*W;
int tt=0;
for(int i=1;i<=n;i++){
int ct=0;
for(int px=Mat[i].lx;px<Mat[i].rx;px++){
for(int py=Mat[i].ly;py<Mat[i].ry;py++){
//cout<<px<<" "<<py<<"\n";
if(vis[px][py])continue;
vis[px][py]=1;
lim[px][py]=Mat[i].v;
siz[px][py]=(x[px+1]-x[px])*(y[py+1]-y[py]);
ct+=siz[px][py];
}
}
vec.push_back(i);
cnt+=ct;
if(i==n||Mat[i+1].v!=Mat[i].v){
ans=ans*solve(Mat[i].v,cnt)%mod;
num-=cnt;
cnt=0;
vec.clear();
}
}
ans=ans*qp(m,num)%mod;
cout<<ans<<"\n";
}
return 0;
}