P3813 [FJOI2017] 矩阵填数 题解
考虑容斥,枚举哪些矩阵中的数 \(<v\)(个数为 \(c\)),哪些 \(\le v\),则系数为 \((-1)^c\)。
考虑将矩阵离散化为 \(\mathcal O(n^2)\) 个块,对于每个子矩阵枚举覆盖的块,更新最大值,最后答案便是 \(\sum_{T\sub S}(-1)^{|T|}\prod_{block}\max_{block}^{size_{block}}\)。
参考代码:
#include<bits/stdc++.h>
#define ll long long
#define md 1000000007
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rept(i,a,b) for(int i=(a);i<(b);++i)
#define drep(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
int T,h,w,m,n,t1,t2,d1[23],d2[23],f[23][23];
ll ans;
struct node{
int x1,y1,x2,y2,c;
inline void in(){
scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);
d1[++t1]=x1,d1[++t1]=x2+1;
d2[++t2]=y1,d2[++t2]=y2+1;
}
}a[12];
ll power(ll x,int y){
ll ans=1;
for(;y;y>>=1){
if(y&1)ans=ans*x%md;
x=x*x%md;
}
return ans;
}
ll solve(int s){
rept(i,1,t1)rept(j,1,t2)f[i][j]=m;
rept(i,0,n){
int c=((s>>i)&1)?a[i].c-1:a[i].c;
int x1=lower_bound(d1+1,d1+t1+1,a[i].x1)-d1,x2=lower_bound(d1+1,d1+t1+1,a[i].x2+1)-d1;
int y1=lower_bound(d2+1,d2+t2+1,a[i].y1)-d2,y2=lower_bound(d2+1,d2+t2+1,a[i].y2+1)-d2;
rept(x,x1,x2)rept(y,y1,y2)f[x][y]=min(f[x][y],c);
}
ll ans=1;
rept(i,1,t1)rept(j,1,t2){
ans=ans*power(f[i][j],(d1[i+1]-d1[i])*(d2[j+1]-d2[j]))%md;
}
return ans;
}
signed main(){
scanf("%d",&T);
while(T--){
scanf("%d%d%d%d",&h,&w,&m,&n);
t1=t2=2,d1[1]=d2[1]=1,d1[2]=h+1,d2[2]=w+1;
rept(i,0,n)a[i].in();
sort(d1+1,d1+t1+1);t1=unique(d1+1,d1+t1+1)-d1-1;
sort(d2+1,d2+t2+1);t2=unique(d2+1,d2+t2+1)-d2-1;
ans=0;
rept(s,0,1<<n){
if(__builtin_popcount(s)&1)ans=(ans-solve(s))%md;
else ans=(ans+solve(s))%md;
}
cout<<(ans+md)%md<<'\n';
}
return 0;
}

浙公网安备 33010602011771号