数学期望+容斥或离散化
B.Blocks
题解:期望dp,n的规模非常小,一个小trick是处理自环的情况,通过移项移到同一边就可以处理了,在判断全部覆盖可以使用容斥定理或者离散化。离散化注意一些边界问题,而且这题数据略水。
//离散化
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(b)-1;i>=a;i--)
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define VI vector<int>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int N = 15;
ll qpow(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
#define y1 awdjawif
int x1[N],y1[N],x2[N],y2[N];
ll s[1<<N],ns[1<<N],dp[1<<N];
ll inv[20];
bool st[40][40];
vector<int> xx;
vector<int> yy;
int f(int x,VI xx){
return lower_bound(all(xx),x) - xx.begin();
}
int n;
void init(){
sort(all(xx));
sort(all(yy));
xx.erase(unique(all(xx)),xx.end());
yy.erase(unique(all(yy)),yy.end());
int szx = xx.size();
int szy = yy.size();
rep(S,0,1<<n){
ns[S] = 0;
int cnt = 0;
rep(i,0,szx)rep(j,0,szy)st[i][j] = 0;
rep(j,0,n){
if(((1<<j)&S)){
int X1 = f(x1[j],xx),Y1 = f(y1[j],yy);
int X2 = f(x2[j],xx),Y2 = f(y2[j],yy);
rep(a,X1,X2)rep(b,Y1,Y2){
if(!st[a][b]){cnt++;st[a][b] = 1;}
}
}
}
if(cnt == (szx-1) * (szy-1))ns[S] = 1;
}
}
int main(){
//cout << qpow(3, 5);
for(int i=1;i<=11;i++)inv[i] = qpow(i,mod-2);
int T;scanf("%d",&T);
while(T--){
xx.clear();
yy.clear();
scanf("%d",&n);
int W,H;
scanf("%d%d",&W,&H);
rep(i,0,n){
scanf("%d%d%d%d",x1+i,y1+i,x2+i,y2+i);
xx.pb(x1[i]);xx.pb(x2[i]);
yy.pb(y1[i]);yy.pb(y2[i]);
}
xx.pb(0);xx.pb(W);
yy.pb(0);yy.pb(H);
init();
//ll ss = 1ll * W * H;
if(!ns[(1<<n)-1]){
cout << -1 << endl;continue;
}
//for(int i=100;i<150;i++)cout << ns[i] << " ";
// cout << endl;
// cout << ns[1] << endl;
// cout << ns[4] << endl;
// cout << ns[15+128] << endl;
per(i,0,1<<n){
if(ns[i]){
dp[i] = 0;
//cout << i << endl;
}
else {
//ll sz = n;
int c = 0;
long long t = 1;
rep(j,0,n){
if(((1<<j)&i)==0){
t = (t + inv[n] * dp[i|(1<<j)] % mod)%mod;
c++;
}
}
dp[i] = (ll)t * n % mod * inv[c] % mod;
}
}
cout << dp[0] << endl;
//cout << dp[(1<<n)-2] << endl;
}
}
//容斥原理
#include<bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(b)-1;i>=a;i--)
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const int N = 15;
ll qpow(ll a,ll b){ll t = 1;assert(b>=0);for(;b;b>>=1){if(b&1)t=(ll)t*a%mod;a=(ll)a*a%mod;}return t;}
#define y1 awdjawif
int x1[N],y1[N],x2[N],y2[N];
ll s[1<<N],ns[1<<N],dp[1<<N];
ll inv[20];
signed main(){
//cout << qpow(3, 5);
for(int i=1;i<=10;i++)inv[i] = qpow(i,mod-2);
int T;scanf("%lld",&T);
while(T--){
int n;scanf("%lld",&n);
int W,H;
scanf("%lld%lld",&W,&H);
rep(i,0,n){
scanf("%lld%lld%lld%lld",x1+i,y1+i,x2+i,y2+i);
}
rep(i,1,1<<n){
int X1 = 0,Y1 = 0,X2 = W,Y2 = H;
rep(j,0,n){
if(i&(1<<j)){
X1 = max(X1,x1[j]);
X2 = min(X2,x2[j]);
Y1 = max(Y1,y1[j]);
Y2 = min(Y2,y2[j]);
}
}
s[i] = 1ll * max(0ll,X2-X1) * max(0ll,Y2-Y1);
//cout << s[i] << endl;
}
rep(i,1,1<<n){
ll v = 0;
for(int j=i;j;j=(j-1)&i){
v += s[j] * (__builtin_parity(j)?1:-1);
}
ns[i] = v;
}
//cout << ns[(1<<n)-1] << endl;
if(ns[(1<<n)-1] < 1ll * W * H){
cout << -1 << endl;continue;
}
// cout << ns[1] << endl;
// cout << ns[4] << endl;
per(i,0,1<<n){
if(ns[i]==1ll * W*H){
dp[i] = 0;
//cout << i << endl;
}
else {
//ll sz = n;
long long t = 1;
int c = 0;
rep(j,0,n){
if(((1<<j)&i)==0){
t = (t + inv[n] * dp[i|(1<<j)] % mod)%mod;
c++;
}
}
dp[i] = (ll)t * n % mod * inv[c] % mod;
}
}
cout << dp[0] << endl;
//cout << dp[(1<<n)-2] << endl;
}
}
浙公网安备 33010602011771号