AtCoder Beginner Contest 189 F
这题有数学做法,但 Feecle6418 - AtCoder 提供了一种思路清奇的DP。
我们第一思路是设为Takahashi到时的期望步数,枚举上一次所在的位置,从转移。
将整个流程反过来。即设为从开始,走到的期望步数。重新整理一下转移:
- 若,则
- 若,则
- 若,则
仔细观察上面的转移,虽然它有环,但是它好像只有一个数是未知的。出现一个未知的数时我们不妨保留它,就像解方程中的一样,看看后面能否找到登录关系。
保留之后,我们惊喜的发现,可以看成一个关于的代数式,且这个代数式的次数就是。
我们不妨设,只转移和就可以了。直接转移是的,但是可以通过前缀和优化到。
最终答案是。可以发现,也可以通过上面方法递推得到,故我们可以得到等式,解这个方程就可以得到。
时间复杂度为。
#include<bits/stdc++.h>
const int maxn=100005;
int n,m,k;
int a[maxn];
struct kb {
double k,b;
}dp[maxn],sum;
int main() {
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;i++) {
int pos;
scanf("%d",&pos);
a[pos]=1;
}
for(int i=1;i<=n;i++) {
int j=i;
while(a[j]) j++;
if(j-i>=m) {
puts("-1");
return 0;
}
}
dp[n]=(kb){0,0};
sum=dp[n];
for(int i=n-1;;i--) {
if(a[i]) dp[i]=(kb){1,0};
else dp[i]=(kb){sum.k/double(m),sum.b/double(m)+1};
if(!i) break;
sum.k+=dp[i].k,sum.b+=dp[i].b;
if(i+m<=n) sum.k-=dp[i+m].k,sum.b-=dp[i+m].b;
}
double res=(-dp[0].b)/(dp[0].k-1);
printf("%.10lf\n",res);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!