数学期望+容斥或离散化

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;
    }
}
posted @ 2022-05-03 20:44  mafengfa  阅读(56)  评论(0)    收藏  举报