[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 }