题解 - P1487 失落的成绩单

· · 题解

一种思维难度只有 黄 的做法

请注意这个解法的复杂度为 O(n),不是最优的,但实际能 相当优秀地 通过本题。

为了让你不用一直切换到题面页,我帮你把柿子复制过来了哦:

A_i=\frac {A_{i-1}-A_{i+1}} 2 +d\quad (i=2, 3, \dots, n-1)

上式中 i 有 (n-2) 种取值。

首先你看:当 i=2 时,我们可以得到一个等量关系

A_2=\frac {A_1-A_3} 2 +d 同理,$i$ 取所有 $(n-2)$ 种取值的任何一个,都会产生一个关于 $A$ 中的项的方程! 那么 $A$ 中有多少个未知数呢?$A_1, A_n$ 已知,所以有 $(n-2)$ 个未知数。 **未知数和方程的数量相等的线性方程组 _有很大的可能_ 可以解得唯一的一组解!** 如果直接写 **高斯消元** (解线性方程组的算法)的模板,本题就解决了。但有一种便捷的方法: > 现在离那个柿子有点远了,我又帮你移下来了,快谢谢我( $$A_i=\frac {A_{i-1}-A_{i+1}} 2 +d$$ 柿子是 $A$ 数列中连续的 $3$ 个元素的关系,所以只要知道 $A_1, A_2$ 的值,代入 $i=2$ 时的方程,并解开,就可以得到 $A_3$,进而通过 $A_2, A_3$ 得到 $A_4$……最终推得 $A$ 的所有 $n$ 项的值!就像这样, 两边乘以 $2$: $$2A_i=A_{i-1}-A_{i+1}+2d$$ 移项: $$A_{i+1}=A_{i-1}-2A_i+2d$$ 那我们面临的问题就是:我们只知道 $A_1$ 而不知道 $A_2$。现在,**想想还没用到的条件!** 是什么?是我们的 $A_n$ 的值对不对? 于是,我们可以设 $A_2=x$,用上面的方法把 $A$ 的所有项求出。(这里的求出,指的是表示成 $3x+4$ 或 $-x+5$ 这样含 $x$ 的式子) 最后得到 $A_n =\ ?x\ +\ ?$。可是,我们已经知道 $A_n$ 是多少了! 于是代入解出 $x$。再代入到 $A_m=\ ?x\ +\ ?$ 之中,就可以得到不含 $x$ 的 $A_m$ 的数值了! 写在代码里时,用 $k_i,b_i$ 表示 $A_i=kx+b$ 即可。 ```cpp // A_1, A_n 是输入的数值。 k[1]=0; b[1]=A_1; k[2]=1; b[2]=0; for (int i=3; i<=n; i++) { k[i] = k[i-2] - 2*k[i-1]; b[i] = b[i-2] - 2*b[i-1] + 2*d; } double x = (A_n-b[n]) / k[n]; cout<<fixed<<setprecision(3) << k[m]*x + b[m]; ```