跳一跳 概率与期望
题目描述
现有一排方块,依次编号为 (1...n)。
方块 (1) 上有一个小人,已知当小人在方块 (i)上时,下一秒它会等概率地到方块 (i)(即不动),方块(i+1) ,方块(i+2)$ …(方块)n$ 上。
求小人到达方块(n) 所需要的期望时间(单位:秒)。
输入格式
一个数字(n) 。
输出格式
若答案 (ans=frac{A}{B})输出(A imes B ^{-1} mod(10^9+7)) 。其中(B^{-1}) 表示(B mod (10^9+7)) 下的逆元。
样例
样例输入 1
1
样例输出 1
0
样例输入 2
10000000
样例输出 2
406018741
数据范围与提示
对于(50\%) 的数据,(n leq 10^6)。
对于(100\%) 的数据,(1 leq n leq 10^7)。
分析
我们设(f[i])为从位置(i)到达位置(n)的期望步数
初始时有(f[n]=0)
很显然(f[i]=(f[i]+f[i+1]+f[i+2]+...+f[n])/(n-i+1)+1)
因为式子左右两边都含有(f[i]),因此我们需要将其消掉
我们在式子左右两边同时乘上((n-i+1))
那么会有 (f[i] imes (n-i+1)=f[i]+f[i+1]+f[i+2]+...+f[n]+n-i+1)
移项会有(f[i] imes (n-i)= sum_{j=i+1}^nf[j] + n-i+1)
因此(f[i]=(sum_{j=i+1}^nf[j] + n-i+1) imes (n-i)^{-1})
转移时顺便记录一下后缀和
因为这道题卡空间,所以(f)不能开数组,要用变量滚动
代码
#include<cstdio>
const int maxn=1e7+5;
const int mod=1e9+7;
int ny[maxn],n,ans,sum;
int main(){
scanf("%d",&n);
ny[1]=1;
for(int i=2;i<=n;i++){
ny[i]=1LL*(mod-mod/i)*ny[mod%i]%mod;
}
ans=0;
for(int i=n-1;i>=1;i--){
ans=1LL*(sum+n-i+1LL)*ny[n-i]%mod;
sum=(sum+ans)%mod;
}
printf("%d
",ans);
return 0;
}