https://atcoder.jp/contests/abc189/tasks/abc189_f
这题发现倒着推就是个解方程了
设dp[i]表示从i位置到结束还要走i步
可知dp[i]=(dp[i+1]+dp[i+2]...dp[i+m])/m+1,如果dp[i+k]是回到0的那么dp[i+k]=dp[0]
所以我们记录一个关于dp[0]的参数k和一个常数b,dp[i]=k*dp[0]+b
然后从后往前扫,维护一个滑动窗口的总参数和k和常数b
那么dp[i]=(k*dp[0]+b)/m+1
推到dp[0]的时候,就是dp[0]=k*dp[0]+b,k=1时无解
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=3e5+10;
const double eps=1e-6;
inline int sgn(double x)
{
if(x>-eps && x<eps)
return 0;
if(x>0) return 1;
else return -1;
}
int n,m,k,cnt,tot,cas,ans;
double dp[maxl][2];
bool vis[maxl];
char s[maxl];
inline void prework()
{
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++)
{
int x;scanf("%d",&x);
vis[x]=true;
}
int l=n+1,r=n+m;
double k=0,b=0;
for(int i=n-1;i>=0;i--)
{
if(vis[i+m+1])
k-=1,b-=0;
else
k-=dp[i+m+1][0],b-=dp[i+m+1][1];
if(vis[i+1])
k+=1,b+=0;
else
k+=dp[i+1][0],b+=dp[i+1][1];
if(vis[i])
continue;
dp[i][0]=k/m;dp[i][1]=b/m+1;
}
if(sgn(dp[0][0]-1)==0)
puts("-1");
else
printf("%.4f\n",dp[0][1]/(1.0-dp[0][0]));
}
inline void mainwork()
{
}
inline void print()
{
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}