BZOJ2319 : 黑白棋遊戲

Claris發表於2017-10-16

將01串按1分段,那麼分析可得長度為$a$的段拼上長度為$b$的段的SG值為$a-[a\leq b]$。

設$f[i][j][k][l]$表示從後往前用了$i$個1,$j$個0,當前段長度為$k$,後面部分SG值為$l$的概率。

同時預處理出$g[i][j][k]$表示$i$個1,$j$個0的串,SG值為$k$的概率。

那麼對於最終答案,只需要DP出組合遊戲的SG值$>0$的概率即可。

時間複雜度$O(m^4+nm^2)$。

 

#include<cstdio>
const int N=105,M=130;
const double eps=1e-12;
int n,ma,mb,o,i,j,k,l,a[N],b[N];double f[2][N][N][N],g[N][N][N],dp[N][M],ans;
int main(){
  scanf("%d",&n);
  for(i=1;i<=n;i++){
    scanf("%d",&a[i]);
    if(a[i]>ma)ma=a[i];
  }
  for(i=1;i<=n;i++){
    scanf("%d",&b[i]);
    if(b[i]>mb)mb=b[i];
  }
  f[1][0][1][0]=f[0][1][1][0]=1;
  for(o=i=0;i<=ma;o^=1,i++){
    if(i)for(j=0;j<=mb;j++)for(k=1;k<=mb+1;k++)for(l=0;l<=mb+1;l++)f[o^1][j][k][l]=0;
    for(j=0;j<=mb;j++)for(k=1;k<=mb+1;k++)for(l=0;l<=mb+1;l++)if(f[o][j][k][l]>eps){
      if(i<ma)f[o^1][j][1][k-(k<=l)]+=f[o][j][k][l]*(i+1)/(i+j+1);
      if(j<mb)f[o][j+1][k+1][l]+=f[o][j][k][l]*(j+1)/(i+j+1);
      g[i][j][k-(k<=l)]+=f[o][j][k][l];
    }
  }
  dp[0][0]=1;
  for(i=1;i<=n;i++)for(j=0;j<M;j++)if(dp[i-1][j]>eps)
    for(k=0;k<=b[i]+1;k++)if(g[a[i]][b[i]][k]>eps)
      dp[i][j^k]+=dp[i-1][j]*g[a[i]][b[i]][k];
  for(i=1;i<M;i++)ans+=dp[n][i];
  return printf("%.6f",ans),0;
}

  

相關文章