F - Sugoroku2(期望dp)

F - Sugoroku2

期望dp: f u f_u fu表示到达终点的期望于是有
f u = { 0 , u ≥ n f 0 , u ∈ A f u + 1 + ⋯ + f u + m m + 1 f_u=\begin{cases} 0,u\ge n \\f_0,u\in A\\ \frac{f_{u+1}+\dots+f_{u+m}}{m}+1 \end{cases} fu=0,unf0,uAmfu+1++fu+m+1

由于存在返回 f 0 f_0 f0的操作,最终出来一定是一个关于 f 0 f_0 f0的方程,对于每个点维护 f 0 f_0 f0的系数和常数即 f u = k f 0 + b f_u=k f_0+b fu=kf0+b

最后解方程即 f 0 = k f 0 + b f_0=k f_0+b f0=kf0+b,显然 k = 1 k=1 k=1时无解。

对于更新每一个 f u = f u + 1 + ⋯ + f u + m m + 1 f_u= \frac{f_{u+1}+\dots+f_{u+m}}{m}+1 fu=mfu+1++fu+m+1可以记录后缀和优化

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<random>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll,int> pli;
typedef pair<int,int> pii;
const ll mod=1e9+7;
const int N=200010;
long double f[N][2];
long double sum[N][2];
bool st[N];
int n,m,k;
int main()
{
    
    
    IO;
    int T=1;
    //cin>>T;
    while(T--)
    {
    
    
        cin>>n>>m>>k;
        for(int i=1;i<=k;i++)
        {
    
    
            int a;
            cin>>a;
            st[a]=1;
        }
        f[n][0]=0,f[n][1]=0;
        for(int i=n-1;i>=0;i--)
        {
    
    
            if(st[i]) f[i][0]=1,f[i][1]=0;
            else
            {
    
    
                f[i][0]=(sum[i+1][0]-sum[i+1+m][0])/m;
                f[i][1]=(sum[i+1][1]-sum[i+1+m][1])/m+1.0;
            }
            sum[i][0]=sum[i+1][0]+f[i][0];
            sum[i][1]=sum[i+1][1]+f[i][1];
        }
        if(fabs(f[0][0]-1.0)<1e-6) puts("-1");
        else printf("%.4llf\n",f[0][1]/(long double)(1.0-f[0][0]));
    }
    return 0;
}

训练赛真的垃圾,努力训练
要加油哦~

猜你喜欢

转载自blog.csdn.net/Fighting_Peter/article/details/113090689
f2