又被我轻轻松松切掉了呢
定义 d p [ i ] dp[i] dp[i]为 [ i , n ] [i,n] [i,n]获得分数的期望
那么显然 d p [ n + 1 ] = 0 dp[n+1]=0 dp[n+1]=0
但是发现无法转移,因为分数的计算需要知道 i i i后面连续 o o o的个数
而且 o o o不固定,那么我们可以维护连续 o o o的期望,记作 n u m [ i ] num[i] num[i]
这样当 a [ i ] = = ′ x ′ a[i]=='x' a[i]==′x′
n u m [ i ] = 0 , d p [ i ] = d p [ i + 1 ] num[i]=0,dp[i]=dp[i+1] num[i]=0,dp[i]=dp[i+1]
这个显然,自己是叉就不连续了
当 a [ i ] = = ′ o ′ a[i]=='o' a[i]==′o′
这个时候需要先减去以 i + 1 i+1 i+1开头的连续 o o o期望得分,再加上以 i i i开头连续 o o o的期望
d p [ i ] = d p [ i + 1 ] − n u m [ i + 1 ] ∗ n u m [ i + 1 ] + ( n u m [ i + 1 ] + 1 ) ∗ ( n u m [ i + 1 ] + 1 ) dp[i]=dp[i+1]-num[i+1]*num[i+1]+(num[i+1]+1)*(num[i+1]+1) dp[i]=dp[i+1]−num[i+1]∗num[i+1]+(num[i+1]+1)∗(num[i+1]+1)
当 a [ i ] = = ′ ? ′ a[i]=='?' a[i]==′?′
就是各占一半的可能,加起来除以2即可
补充一下:这题从前往后转移也行
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=3e5+10;
int n;
long double dp[maxn],num[maxn];
char a[maxn];
signed main()
{
cin >> n >> (a+1);
dp[n+1]=0,num[n+1]=0;
for(int i=n;i>=1;i--)
{
long double x=num[i+1];
if( a[i]=='x' ) dp[i]=dp[i+1],num[i]=0;
else if( a[i]=='o' )
{
dp[i]=dp[i+1]-x*x+(x+1)*(x+1);
num[i]=num[i+1]+1;
}
else
{
dp[i]=dp[i+1]/2+( dp[i+1]-x*x+(x+1)*(x+1) )/2;
num[i]=( num[i+1]+1 )/2;
}
}
printf("%.4Lf",dp[1]);
}