跳一跳
题目描述
现有一排方块,依次编号为
1
…
n
1\ldots n
1…n。
方块 1 上有一个小人,已知当小人在方块 i 上时,下一秒它会等概率地到方块 i(即不动),方块 i+1,方块 i+2……方块 n 上。
求小人到达方块 n 所需要的期望时间(单位:秒)。
输入格式
一个数字 n。
输出格式
若答案 a n s = A B ans=\frac{A}{B} ans=BA 输出 A × B − 1 m o d ( 1 0 9 + 7 ) A \times B^{-1} \bmod (10^9+7) A×B−1mod(109+7)。其中 B − 1 B^{-1} B−1 表示 B m o d ( 1 0 9 + 7 ) B \bmod (10^9+7) Bmod(109+7) 下的逆元。
样例 1
输入样例
1
输出样例
0
样例 2
输入样例
10000000
输出样例
406018741
数据范围与约定
对于
50
%
50\%
50% 的数据,
n
⩽
1
0
6
n \leqslant 10^6
n⩽106。
对于
100
%
100\%
100% 的数据,
1
⩽
n
⩽
1
0
7
1 \leqslant n \leqslant 10^7
1⩽n⩽107。
思路
设 d p [ i ] dp[i] dp[i]为从 i 点出发到达 n 点的期望时间,然后从后向前递推。
原题
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 6;
const ll mod = 1e9 + 7;
int inv[maxn]; // 逆元
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
inv[0] = 1;
inv[1] = 1;
for (int i = 2; i <= n; i++) // 预处理逆元
inv[i] = mod - mod / i * inv[mod % i] % mod;
ll dp = 0; // 为了避免MLE,不能开dp数组
ll sum = 0; // sum记录后缀和
for (int i = n - 1; i >= 1; i--)
{
dp = (sum + n - i + 1) * inv[n - i] % mod;
sum += dp;
sum %= mod;
}
cout << dp << '\n';
return 0;
}