题目链接:https://www.cometoj.com/contest/59/problem/E?problem_id=2714
求期望并且一堆转移基本上就是期望dp了(叉腰
照常的设dp[i]表示i位置到n位置的期望步数。则我们所求的是dp[0]。
初始化dp[n]=0,因为n到n的期望为0。
之后先讨论下i为n-1到n-k的时候。
我们可以列出转移方程(随便写几个
$dp[n-1]=\tfrac{1}{k}*(dp[n]+dp[n-1]+dp[n-2]+\cdot \cdot \cdot +dp[n-k+1])+1$
$dp[n-2]=\tfrac{1}{k}*(dp[n-1]+dp[n]+dp[n-1]+\cdot \cdot \cdot +dp[n-k+2])+1$
$\cdot \cdot \cdot\cdot \cdot \cdot$
$dp[n-k]=\tfrac{1}{k}*(dp[n-k+1]+dp[n-k+2]+dp[n-k+3]+\cdot \cdot \cdot +dp[n])+1$
这时候自(mang)信(fu)同学可能就直接上高斯消元了,而善于发现的老哥则会很轻松的写出一组解,即:$dp[n-1]=dp[n-2]=dp[n-3]=\cdot \cdot \cdot =dp[n-k]=k$
之后再讨论下i为n-k-1到0的时候
就是很简单的转移:$dp[i]=\tfrac{1}{k}*(dp[i+k]+dp[i+k-1]+dp[i+k-2]+\cdot \cdot \cdot +dp[i+1])+1$
这里就可以直接矩阵快速幂优化。
先上一个8/15AC,7/15RE的不加速代码方便理解:
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 using namespace std; 7 typedef long long ll; 8 const int maxn = 2e5 + 10; 9 const ll mod = 1000000007; 10 ll dp[maxn]; 11 ll qpow(ll a, ll b) { 12 ll ans = 1; 13 while (b) { 14 if (b & 1)ans = ans * a%mod; 15 a = a * a%mod; 16 b >>= 1; 17 } 18 return ans; 19 } 20 int main() { 21 ll n, k; 22 cin >> n >> k; 23 ll inv = qpow(k, mod - 2); 24 dp[n] = 0; 25 ll sum = 0; 26 for (int i = n - 1; i >= n - k; i--) 27 dp[i] = k, sum = (sum + dp[i]) % mod; 28 for (int i = n - k - 1; i >= 0; i--) 29 dp[i] = (sum * inv + 1) % mod, sum = (sum - dp[i + k] + dp[i] + mod) % mod; 30 printf("%lld\n", dp[0]); 31 }
之后是本题正解:(先咕咕一下
原文地址:https://www.cnblogs.com/sainsist/p/11323696.html