天依题 +1 || solution - P9156

· · 题解

南北组太甜了啊啊啊。

可能看上去有点吓人,但实际上还是比较简单的。

考虑 dp,注意到结果仅和剩余牌数和已知的牌数有关,所以令 f_{i,j} 表示剩余 i 对牌,其中有 j 张已知,此时先手期望得分比后手期望得分高的分数。

先不考虑平局。令已知点数为 S,牌 x 的点数表示为 v_x,有三种操作方式:

然后再来看平局的情况。注意到如果按照第一种情况,从本身的负状态转移,那么后手也一定会从本身的负状态转移,这样就导致了游戏无法结束,于是就不得不平局了。所以平局就等价于跟 0\max

时间复杂度 O(n^2)

注意到多测,但不需要也不能清空,因为对于任意 f_{i,j} 的取值与总数无关。如果清空则会在复杂度上乘上一个 T,会 T 飞。

需要进行一些特判,具体见代码。

代码:

int n,m;
double f[N][N];
bitset <N> vis[N];

il double dp(int i,int j)
{
    if(i<=0 || j<0 || i<j) return 0.;
    if(vis[i][j]) return f[i][j];

    f[i][j]=(j>=2 ? 0. : -1e100);
    j>=1 && chmax(f[i][j] , (1.*(1+dp(i-1,j-1)) - 1.*(j-1)*(1+dp(i-1,j-1)) - 2.*(i-j)*dp(i,j+1)) /(2*i-j));
    2*i-j>=2 && chmax(f[i][j] , (1.*(i-j)*(1+dp(i-1,j)) - 1.*j*(j-1)/2.*(2+dp(i-2,j-2)) - 2.*j*(i-j)*(1+dp(i-1,j)) - 2.*(i-j)*(i-j-1)*dp(i,j+2)) *2./(2*i-j)/(2*i-j-1));

    return vis[i][j]=1,f[i][j];
}

il void solve()
{
    read(n,m);
    printf("%.20Lf\n",n/2.+dp(n,m)/2.);
}

华风夏韵,洛水天依!