转载自:霍纳法则在多项式求值中的应用
在信息学奥赛中,我们有时会遇到多项式求值的问题。对于多项式求值问题,我们最容易想到的算法是求出每一项的值然后把所求的值累加起来,这种算法的时间和空间效率都不高,对于数据规模不大的题目来说由于其直观、简单很容易被大家采纳,可一旦数据规模过大时,这种算法就显得无能为力了,下面介绍一种解决这类求值问题的高效算法――霍纳法则。
一﹑霍纳法则介绍
假设有n+2个实数a0,a1,…,an,和x的序列,要对多项式Pn(x)= anxn +an-1xn-1+…+a1x+a0求值,直接方法是对每一项分别求值,并把每一项求的值累加起来,这种方法十分低效,它需要进行n+(n-1)+…+1=n(n+1)/2次乘法运算和n次加法运算。有没有更高效的算法呢?答案是肯定的。通过如下变换我们可以得到一种快得多的算法,即Pn(x)= anxn +an-1xn-1+…+a1x+a0=((…(((anx+an-1)x+an-2)x+ an-3)…)x+a1)x+a0,这种求值的安排我们称为霍纳法则。
例如,当x=3时,计算p(x)=2x4-x3+3x2+x-5的值。对于多项式p(x)=2x4-x3+3x2+x-5,我们按霍纳法则进行变换,有:
p(x)=2x4-x3+3x2+x-5
=x(2x3-x2+3x+1)-5
=x(x(2x2-x+3)+1)-5
=x(x(x(2x-1)+3)+1)-5
在实际的操作过程中,为了得到上式,我们没有必要经过上述的特定变换,我们只需要一个该多项式系数的原始列表。我们可以方便地用一个二维表格来帮助我们笔算求出这个多项式的值。该表第一行包含了该多项式的系数(如果存在等于0的系数,也都包含进来),从最高的an到最低的a0。第二行中除了第一个和第二个单元格用来存储x和an外,其它单元格都用来存储中间结果。在作了这样的初始化后,在计算第二行的某一个单元格的值时,用该单元格的前一个单元格乘以x的值再加上该单元格的第一行的系数即可。用这种方式算出的最后一个单元格的值,就是该多项式的值。
系数 | a4 | a3 | a2 | a1 | a0 |
2 | -1 | 3 | 1 | -5 | |
x=3 | 2 | 3*2-1=5 | 3*5+3=18 | 3*18+1=55 | 3*55-5=160 |
所以,P(3)=160。我们拿表格中的单元格和多项式x(x(x(2x-1)+3)+1)-5做比较,我们会发现3*2-1=5是2x-1在x=3时的值,3*5+3=18是x(2x-1)+3在x=3时的值,3*18+1=55是x(x(2x-1)+3)+1在x=3时的值,最后3*55-5=160是x(x(x(2x-1)+3)+1)-5在x=3时的值。
二﹑霍纳法则的程序实现
上述的计算过程我们可以用一个递推的关系表示,即Pi(x)= xPi-1(x)+an-i,递推的临界值P0(x)= an,其中i=1…n。具体在实现时使用了滚动数组技术。
PASCAL语言代码如下:
function horner(x:integer):longint;//求形如anxn +an-1xn-1+…+a1x+a0多项式的值,a[i]数组用于存放系数ai。
var
p:longint;
i:integer;
begin
p:=a[n];
for i:=1 to n do
p:=x*p+a[n-i];
horner:=p;
end;
三﹑霍纳法则的应用
霍纳法则在多项式求值运算中的应用,显示出了算法的高效性和优雅性。下面就是霍纳法则的一个典型的应用。
奇怪的贸易(题目来源:game journey国庆模拟赛):刚结束了CS战斗的小D又进入了EVE的游戏世界,在游戏中小D是一名商人,每天要做的事情就是在这里买东西,再运到那里去卖.这次小D来到了陌生的X星,X星上有n种货物,小D决定每种都买走一些,他用ai来表示第i种货物购买的数量,X星人对物品的单价有特别的决定方式.他们首先会选择一个基本价x(x为整数),第一种物品单价为x,第二种物品单价为x2,第三种物品单价为x3……第i种物品单价为xi.结算总价时,你还需要给他们一笔手续费a0,小D不知道自己带的钱是否能够进行这笔交易,所以请你帮助他计算这笔交易他要支付的总金额是多少
输入格式:
x n
a0
a1
a2
.
.
.
an
第一行两个数分别表示基准价x (x<=10),物品种数n (n<=100000)
第二行一个数,手续费a0 (a0<=100)
接下来的n行每行一个数,第i行表示第i种物品购买的数量(ai<=100)
输出格式:
输出结果的最后100位,若不足100位请高位用零补足
样例输入:
2 3
4
3
2
1
样例输出:
000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000026
数据规模:
对20%的数据,n<=10
对50%的数据,n<=200
对100%的数据,n<=100000