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,u≥nf0,u∈Amfu+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;
}
训练赛真的垃圾,努力训练
要加油哦~