51nod 1258 序列求和 V4 拉格朗日插值法求自然数幂和

题意

T(n) = n^k,S(n) = T(1) + T(2) + …… T(n)。给出n和k,求S(n)。
例如k = 2,n = 5,S(n) = 1^2 + 2^2 + 3^2 + 4^2 + 5^2 = 55。
由于结果很大,输出S(n) Mod 1000000007的结果即可。
1 <= T <= 500,1 <= N <= 10^18, 1 <= K <= 50000

分析

拉格朗日插值法:
如果知道一个n次多项式f(x)上的n+1个点(x0,y0),(x1,y1),…,(xn,yn),现在我们知道x’,要求y’。
那么我们可以构造一个多项式 f(x)=b0(x)y0+b1(x)y1+...+bn(x)yn 其中 bk(x) 均为n次多项式。
要使这个多项式满足这n+1个点,则有 bk(xk)=1,bk(xk)=0(k!=k) ,那么 xk 必然是 bk(x) 的一个根。
不难发现有

bk(x)=ni=0,i!=k(xxi)ni=0,i!=k(xkxi)

那么我们就可以通过把x’代进这条式子里面来求出y’。

再回到这题,设 ans(x)=xi=1ik ,那么显然ans必然是一个k+1次的多项式。我们可以先通过快速幂把 ans(i)(1<=i<=k+2) 求出,然后通过拉格朗日乘数法来求出 ans(n) 。注意到每一项分子和分母都是两段连续的数相乘,那么我们就可以在较短的时间内把该式子算出来。

代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long LL;

const int N=50005;
const int MOD=1000000007;

int k,a[N],ny[N],pow[N],p[N],q[N];
LL n;

int ksm(int x,int y)
{
    int ans=1;
    while (y)
    {
        if (y&1) ans=(LL)ans*x%MOD;
        x=(LL)x*x%MOD;y>>=1;
    }
    return ans;
}

int solve(LL x)
{
    if (x<=k+2) return a[x];
    x%=MOD;
    int w=ksm(pow[k+2],MOD-2);LL ans=0;
    p[0]=q[k+3]=1;
    for (int i=1;i<=k+2;i++) p[i]=(LL)p[i-1]*(x-i)%MOD;
    for (int i=k+2;i>=1;i--) q[i]=(LL)q[i+1]*(x-i)%MOD;
    for (int i=1;i<=k+2;i++)
    {
        (ans+=(LL)a[i]*w%MOD*p[i-1]%MOD*q[i+1])%=MOD;
        w=(LL)w*(i-k-2)%MOD*ny[i]%MOD;
    }
    ans+=ans<0?MOD:0;
    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    for (int i=1;i<=50002;i++) ny[i]=ksm(i,MOD-2);
    pow[1]=1;
    for (int i=2;i<=50002;i++) pow[i]=(LL)pow[i-1]*(1-i)%MOD;
    while (T--)
    {
        scanf("%lld%d",&n,&k);
        for (int i=1;i<=k+2;i++) a[i]=a[i-1]+ksm(i,k),a[i]-=a[i]>=MOD?MOD:0;
        printf("%d\n",solve(n));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值