[uoj422]小Z的礼物

记$S=\{(i,j)\mid s_{i,j}=*\},T_{i,j}$表示获得$(i,j)$上礼物的时间,问题即求$E(\max_{(i,j)\in S}T_{i,j})$

考虑$\min\max$容斥,即$\max_{(i,j)\in S}T_{i,j}=-\sum_{S'\subseteq S}(-1)^{|S'|}\min_{(i,j)\in S'}T_{i,j}$

根据定义,不难得到$E(\min_{(i,j)\in S'}T_{i,j})=\frac{2nm-n-m}{cnt}$(其中$cnt$为与$S'$有交的相邻格子对数)

根据期望的线性性,问题即求$\sum_{S'\subseteq S}(-1)^{|S'|}\frac{2nm-n-m}{cnt}$,显然可以使用状压dp计算

时间复杂度为$o(n^{2}m^{2}2^{n})$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 10
 4 #define M 105
 5 #define K 70
 6 #define T 1205
 7 #define mod 998244353
 8 #define ll long long
 9 int n,m,t,ans,inv[T],f[M][N][K][T];
10 char s[N][M];
11 int main(){
12     inv[0]=inv[1]=1;
13     for(int i=2;i<T;i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
14     scanf("%d%d",&n,&m),t=2*n*m-n-m;
15     for(int i=1;i<=n;i++)scanf("%s",s[i]+1);
16     int SS=0;
17     for(int i=1;i<=n;i++)
18         if (s[i][1]=='*')SS|=(1<<i-1);
19     for(int S=SS;;S=((S-1)&SS)){
20         int cnt1=__builtin_popcount(S);
21         int cnt2=__builtin_popcount((S|(S<<1))&((1<<n)-2));
22         f[1][n][S][cnt2]=1;
23         if (cnt1&1)f[1][n][S][cnt2]=mod-1;
24         if (!S)break;
25     }
26     for(int j=2;j<=m;j++)
27         for(int i=1;i<=n;i++)
28             for(int S=0;S<(1<<n);S++)
29                 for(int k=0;k<=t;k++){
30                     int S0=(S>>1),S1=(S0|(1<<n-1));
31                     if (i==1){
32                         int kk=k+(S&1);
33                         f[j][i][S0][kk]=(f[j][i][S0][kk]+f[j-1][n][S][k])%mod;
34                         if (s[i][j]=='*')f[j][i][S1][k+1]=(f[j][i][S1][k+1]-f[j-1][n][S][k]+mod)%mod;
35                     }
36                     else{
37                         int kk=k+(S&1)+(S>>n-1);
38                         f[j][i][S0][kk]=(f[j][i][S0][kk]+f[j][i-1][S][k])%mod;
39                         if (s[i][j]=='*')f[j][i][S1][k+2]=(f[j][i][S1][k+2]-f[j][i-1][S][k]+mod)%mod;
40                     }
41                 }
42     for(int S=0;S<(1<<n);S++)
43         for(int k=1;k<=t;k++)ans=(ans+(ll)t*inv[k]%mod*f[m][n][S][k])%mod;
44     ans=(mod-ans)%mod,printf("%d\n",ans);
45     return 0;
46 }
View Code

 

posted @ 2022-03-11 19:12  PYWBKTDA  阅读(62)  评论(0编辑  收藏  举报