基本公式
给定
n
+
1
n+1
n+1个横坐标不相同的点,可以唯一确定一个
n
n
n次的多项式
f
(
x
)
f(x)
f(x)。
(
x
1
,
y
1
)
(
x
2
,
y
2
)
.
.
.
(
x
n
+
1
,
y
n
+
1
)
(x_1,y_1)\quad(x_2,y_2)...\quad(x_{n+1},y_{n+1})\quad
(x1,y1)(x2,y2)...(xn+1,yn+1)
可以通过构造得到多项式
f
(
x
)
=
∑
i
=
1
n
+
1
y
i
∏
j
≠
i
x
−
x
j
x
i
−
x
j
f(x)=\sum_{i=1}^{n+1}y_i\prod_{j\neq i}\frac{x-x_j}{x_i-x_j}\\
f(x)=i=1∑n+1yij=i∏xi−xjx−xj
把点带进去可以验证,这样可以
O
(
n
2
)
O(n^2)
O(n2)计算。
注意: 多带几个点进去不会影响结果。
应用
如果
x
x
x取值为连续的,
1
≤
x
≤
n
+
1
1\le x\le n+1
1≤x≤n+1,计算
f
(
k
)
f(k)
f(k)代入公式
f
(
k
)
=
∑
i
=
1
n
+
1
y
i
∏
j
≠
i
k
−
j
i
−
j
f(k)=\sum_{i=1}^{n+1}y_i\prod_{j\neq i}\frac{k-j}{i-j}\\
f(k)=i=1∑n+1yij=i∏i−jk−j
则很明显可以看出有阶乘的形式,可以进行预处理,时间复杂度降为
O
(
n
)
O(n)
O(n)。例题
namespace polysum
{
const int D=1e6+9;
ll p[D],p1[D],p2[D];
ll qpow(ll a,ll b){ll res=1;a%=mod;while(b){if(b&1)res=res*a%mod;a=a*a%mod;b>>=1;}return res;}
void init(int n)//x=1~n
{
ll res=1;
for(int i=1; i<=n; i++)res=res*(ll)i%mod;
res=qpow(res,mod-2);
p[n]=res;
for(int i=n-1;i>=0;i--)
p[i]=p[i+1]*(i+1)%mod;
}
ll polysum(int n,ll *a,ll m)//a[1]...a[n] a[m]
{
if(1<=m&&m<=(ll)n)
return a[(int)m];
ll res=0;
p1[1]=p2[n]=1;
for(int i=2; i<=n; i++)p1[i]=p1[i-1]*(ll)(m-i+1)%mod;
for(int i=n-1; i>=1; i--)p2[i]=p2[i+1]*(ll)(m-i-1)%mod;
for(int i=1; i<=n; i++)
{
ll tmp=p[i-1]*p[n-i]%mod;
if((n-i)&1)tmp=tmp*(mod-1)%mod;
res=(res+a[i]*p1[i]%mod*p2[i]%mod*tmp%mod)%mod;
}
return res;
}
}
重心拉格朗日插值
f ( x ) = ∑ i = 1 n + 1 y i ∏ j ≠ i x − x j x i − x j = ∑ i = 1 n + 1 y i 1 x − x i ∏ j = 1 n + 1 ( x − x j ) ∏ j ≠ i 1 x i − x j = ∏ j = 1 n + 1 ( x − x j ) ∑ i = 1 n + 1 y i 1 x − x i ∏ j ≠ i 1 x i − x j \begin{aligned} f(x)&=\sum_{i=1}^{n+1}y_i\prod_{j\neq i}\frac{x-x_j}{x_i-x_j}\\ &=\sum_{i=1}^{n+1}y_i\frac{1}{x-x_i}\prod_{j=1}^{n+1}(x-x_j)\prod_{j\neq i}\frac{1}{x_i-x_j}\\ &=\prod_{j=1}^{n+1}(x-x_j)\sum_{i=1}^{n+1}y_i\frac{1}{x-x_i}\prod_{j\neq i}\frac{1}{x_i-x_j} \end{aligned} f(x)=i=1∑n+1yij=i∏xi−xjx−xj=i=1∑n+1yix−xi1j=1∏n+1(x−xj)j=i∏xi−xj1=j=1∏n+1(x−xj)i=1∑n+1yix−xi1j=i∏xi−xj1