题目
题目链接:https://ac.nowcoder.com/acm/contest/7612/D
思路
显然要棋子在 ([1,d)) 和 ([d,n]) 的时候分开做。
当棋子在 ([1,d)) 的时候,假设现在在位置 (p),骰子扔到的是 (x) 点,那么棋子可能会变到 (p-x) 或 (x-p) 的位置。
发现只有当 (x) 恰好等于 (p) 的时候才可以结束,否则 (p) 将变为依然在 ([1,d)) 中的另一个位置 (p')。那么其实等价于在 (1sim d-1) 中一直随机一个数,直到随机到 (1) 时停止,求期望次数。
设期望 (s) 次扔到点 (1),那么有
[s=frac{d-2}{d-1}(s+1)+frac{1}{d-1}
]
解方程得到 (s=d-1)。
那么当棋子在 ([1,d)) 时,期望 (d-1) 次才会回到点 (0)。
那么当棋子所在位置 (pgeq d) 时,由于只会不停往左走,所以可以设 (f[i]) 表示点 (i) 开始期望多少次可以回到点 (0),这样是没有后效性的。
时间复杂度 (O(Tn))。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=100010;
int Q,n,d;
double f[N],sum[N];
int main()
{
scanf("%d",&Q);
while (Q--)
{
scanf("%d%d",&n,&d);
f[0]=sum[0]=1;
for (int i=1;i<d;i++)
f[i]=d-1,sum[i]=sum[i-1]+f[i];
for (int i=d;i<=n;i++)
{
f[i]=(sum[i-1]-sum[i-d]+d-1)/d+f[i-d]/d;
sum[i]=sum[i-1]+f[i];
}
printf("%.2lf
",f[n]);
}
return 0;
}