Codeforces Round #604 (Div. 1) - 1C - Beautiful Mirrors with queries
题意
给出排成一列的 \(n\) 个格子,你要从 \(1\) 号格子走到 \(n\) 号格子之后(相当于 \(n+1\) 号格子),一旦你走到 \(i+1\) 号格子,游戏结束。 当你在 \(i\) 号格子时,你有 \(p_i\) 的概率走到 \(i+1\) 号格子,否则你会返回最近的一个 checkpoint (存档点),最近的存档点是指 \(max\{x|x\leq i \; and \; ischeckpoint(x)\}\) 。对于每个 \(query x\) ,会把 \(x\) 号格子的 checkpoint 属性翻转,然后输出此时从 \(1\) 号格子走到 \(n+1\) 号格子的期望步数。
题解
考虑没有 checkpoint 的情况,也就是 2E 的题意。此时有两种比较好的解法:
-
设 \(dp_i\) 表示从 \(1\) 号格子开始,第一次走到 \(i\) 号格子所需的期望步数,则 \(dp_1=0\) ,所求为 \(dp_{n+1}\) 。
对于 \(i+1\) 号格子,走到它有两种可能:成功,从 \(i\) 号格子转移;失败,从 \(1\) 号格子转移。\[dp_{i+1}=p_i(1+dp_i)+(1-p_i)(1+dp_i+dp_{i+1}) \]化简,即
\[dp_{i+1}=\frac{1}{pi}(1+dp_i) \]递推可以求解。
-
设 \(dp_i\) 表示从 \(i\) 号格子开始,第一次走到 \(n+1\) 号格子所需的期望步数,则 \(dp_{n+1}=0\) ,所求为 \(dp_{1}\) 。
对于 \(i\) 号格子,下一步有两种可能:成功,转移到 \(i+1\) 号格子;失败,转移到 \(1\) 号格子。\[dp_i=p_i(dp_{i+1}+1)+(1-p_i)(1+dp_1) \]则有
\[dp_{n+1}=0 \]\[dp_n=p_n(dp_{n+1}+1)+(1-p_n)(1+dp_1) \]\[dp_{n-1}=p_{n-1}(dp_n+1)+(1-p_{n-1})(1+dp_1) \]\[dp_{n-2}=p_{n-2}(dp_{n-1}+1)+(1-p_{n-2})(1+dp_1) \]...
\[dp_3=p_3(dp_4+1)+(1-p_3)(1+dp_1) \]\[dp_2=p_2(dp_3+1)+(1-p_2)(1+dp_1) \]\[dp_1=p_1(dp_2+1)+(1-p_1)(1+dp_1) \]每次把上一个式子代到下一个式子,会使得整个式子只带有 \(dp_1\) 一个未知项,最后把 \(dp_1\) 解出来就可以了。
那么加上 checkpoint ,解法出现了一些变化,只说看起来比较好的第一种。
设 \(dp_i\) 表示从 \(1\) 号格子开始,第一次走到 \(i\) 号格子所需的期望步数,则 \(dp_1=0\) ,所求为 \(dp_{n+1}\) 。
对于 \(i+1\) 号格子,走到它有两种可能:成功,从 \(i\) 号格子转移;失败,从 \(x\) 号格子转移, \(x\) 表示 \(i\) 对应的 checkpoint。
根据期望的线性性,可得 \(cost(x,y)=dp_y-dp_x\) ,表示从 \(x\) 号格子转移到 \(y\) 号格子的花费为两式的差。
化简,即
注意到一开始是没有任何 checkpoint 的(就算有也可以逐个添加进来),先按照 2E 的方法解决好。然后插入第一个 checkpoint \(x\) ,那么显然不比 \(x\) 大的都是不受影响的。
第一个受影响的点即 \(x+1\) :
化简,即
第二个受影响的点即 \(x+2\) (第一种化简格式):
代入,即
化简,即
化简,即
代入第三种化简格式,检验成立
第三个受影响的点即 \(x+3\) (第三种化简格式):
代入,即
化简,即
假设保存有 \(p_i\) 的逆元 \(invp_i\) ,那么这个修改就相当于每个元素依次加上一个前缀积。