拉格朗日插值法(求自然数幂和)

背景

i=1nik,给定n<=1e18,k<=1e6.

分析

g(x)=i=1xik。考虑k=1与k=2时的公式,不难得出每个g(x)实际上都是一个k+1次多项式。(这是猜想,具体证明看http://blog.csdn.net/jokerwyt/article/details/54141757,那个递推式就是k+1次的)

那么问题就变成了已知一个k+1次多项式L(x)的k+2个对应值点(xi,L(xi)), (由于k很小所以暴力求出k+2个对应值点)
求L(或者说L(x0))
这个问题有解且唯一,因为对应方程组有唯一解。
可以使用高斯消元求解,解出系数。时间复杂度为O(k3)

拉格朗日插值法

拉格朗日插值法正是用于解决这种问题。如果点随便给,时间复杂度为O(k^2),但是对于有规律的给出点对(x,y)可以更快。
与中国剩余定理有异曲同工,我们可以写出答案多项式的形式(之一)
L(x)=yili(x)
li(x)是构造的一个函数,满足li(xi)=1li(xj,i!=j)=0
也就是说这个多项式经过给出的每一点。又因为解唯一,所以这就是所求多项式。

li的构造方法比较简单:首先因为li(xj)=0。所以其有根xj.因此有因式(x-xj).
然后对于li(xi)=1,只需要消除上面构造带来的影响,也就是对于j!=i,除掉(xi-xj).
感性告诉我li是唯一构造的.
因此,只需要花费O(k * 计算li(x)的时间)就可以推算出L(x0)的答案了。在这一题中,li在预处理后可以O(1)算出.
对于一段连续的负数相乘,不要傻傻的将其加上mo再算阶乘(过大),直接将负号提出,其余按正数阶乘算

自然数幂和的拉格朗日解法

预处理出f(1..k+2)的值,然后直接拉格朗日插值。因为此处的li是有规律的(数轴上一段数相乘),可以做到O(k)的时间。(负数阶乘记得提出负号)
分子分母分开算。分子前后缀算,很方便。
分母的话是两段阶乘的逆元,注意符号。

ll lag(ll x) {
    if (x<=DMX) return dy[x];
    if (mapp[x]) return mapp[x];
    cnt++;
    pre[0]=1,suf[ZS+1]=1;
    for (ll i=1; i<=ZS; i++) pre[i]=pre[i-1]*(x-i)%mo;
    for (ll i=ZS; i; i--) suf[i]=suf[i+1]*(x-i)%mo;
    ll ret=0;
    for (ll i=1; i<=ZS; i++) {
        ret=(ret+(ll)dy[i]*pre[i-1]%mo*suf[i+1]%mo
            *njc[i-1]%mo*njc[ZS-i]%mo*(((ZS-i)&1)?-1:1)%mo)%mo;
    }
    return mapp[x]=(ret+mo)%mo;
}

注意

据说:
拉格朗日插值法如果要在(mod p)意义下进行的话,那么p只能是质数。
如果要mod非质数的话,那么就要用牛顿插值法。

阅读更多
版权声明:未经作者本人允许禁止转载。 https://blog.csdn.net/jokerwyt/article/details/78165667
个人分类: 新内容 数论
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭