F - Sugoroku2
期望dp:fuf_ufu表示到达终点的期望于是有
fu={0,u≥nf0,u∈Afu+1+⋯+fu+mm+1f_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
由于存在返回f0f_0f0的操作,最终出来一定是一个关于f0f_0f0的方程,对于每个点维护f0f_0f0的系数和常数即fu=kf0+bf_u=k f_0+bfu=kf0+b
最后解方程即f0=kf0+bf_0=k f_0+bf0=kf0+b,显然k=1k=1k=1时无解。
对于更新每一个fu=fu+1+⋯+fu+mm+1f_u= \frac{f_{u+1}+\dots+f_{u+m}}{m}+1fu=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;
}
训练赛真的垃圾,努力训练
要加油哦~