CodeVS3785 项链

http://codevs.cn/problem/3785/

题意:有一个数列E[1]…E[n],当1<i<n时,有E[i]=(E[i-1]+E[i+1])/2+D[i]。

现给定E[1],E[n]以及D[2]…D[n-1],求出完整的E数列。n<=500,000。

由于中间的E[2]…E[n-1]未知,当n>3时没有任何某两个下标差为1或2的已知E值,因此无法直接计算。

我们可以用方程的思想来解决,设E[2]=x,这样联系E[1]和D[2]就可以用x表示出E[3],并且不断利用D表示出E的每一项。

于是我们可以得到一个E[n]=f(x)的方程,并且容易发现这个方程是一次的,直接求解,然后依次返回代入或直接根据相邻项递推即可。

进一步发现,在E[n]=f(x)=kx+b中,k一定等于n-1,这点可以用归纳法证明,因而我们也不用存k了。

程序写起来其实只有十余行,但是具体算法还是有一定思维难度的。

代码:

var
  e,d,b:array[0..500020]of double;
  n,i,l,r,m:longint;
begin
  readln(n,e[1],e[n]);
  for i:=2 to n-1 do read(d[i]);
  b[2]:=0;
  b[3]:=(b[2]-d[2])*2-e[1];
  for i:=4 to n do
    b[i]:=(b[i-1]-d[i-1])*2-b[i-2];
  e[2]:=(e[n]-b[n])/(n-1);
  for i:=3 to n do
    e[i]:=(e[i-1]-d[i-1])*2-e[i-2];
  for i:=1 to n do
    write(e[i]:0:0,' ');
end.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值