[TJOI2018]教科书般的亵渎

题目

怎么没人用\(O(klogn)\)的插值啊

首先

\[\sum_{i=1}^ni^{m+1}\]

是一个以\(n\)为自变量的\(m+2\)次多项式,我们需要\(m+3\)个点才能确定这个多项式

拿出拉格朗日插值的柿子

\[f(x)=\sum_{i=1}^{m+3}y_i\prod_{i\ne j}\frac{x-x_j}{x_i-x_j}\]

我们发现如果我们下面带的点是连续的自然数的话,分母上就是两组阶乘相乘,不过套论一下奇偶性来确定符号

分子上我们直接处理好\(\prod x-x_j\),我们每次乘上\(x-x_i\)的逆元就好了

之后如果\(n<=m+3\)我们直接暴力

代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define LL long long
#define re register
#define maxn
const LL mod=1e9+7;
inline LL read() {
    LL x=0;char c=getchar();while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
int T;
LL n,m,fac[55],a[55];
inline LL quick(LL a,LL b) {LL S=1;while(b) {if(b&1ll) S=S*a%mod;b>>=1ll;a=a*a%mod;}return S;}
inline LL calc(LL n,int m) {
    if(n<=m+2) {
        LL ans=0;
        for(re int i=1;i<=n;i++) ans=(ans+quick(i,m)%mod)%mod;
        return ans;
    }
    LL ans=1,now=0,tot=0;
    for(re int i=1;i<=m+2;i++) 
        ans=(ans*(n-i+mod)%mod)%mod;
    for(re int i=1;i<=m+2;i++) {
        now=now+quick(i,m);now%=mod;
        LL t=ans*quick((n-i+mod)%mod,mod-2)%mod,q=quick(fac[m+2-i]*fac[i-1]%mod,mod-2);
        if((m+2-i)&1) tot-=now*t%mod*q%mod;
            else tot+=now*t%mod*q%mod;
        tot+=mod;tot%=mod;
    }
    return tot;
}
int main() {
    T=read();fac[0]=1;
    for(re int i=1;i<=54;i++) fac[i]=(fac[i-1]*(LL)i)%mod;
    while(T--) {
        n=read(),m=read();
        for(re int i=1;i<=m;i++) a[i]=read();
        std::sort(a+1,a+m+1);
        LL ans=0;
        for(re int i=0;i<=m;i++) {
            ans+=calc(n-a[i],m+1);ans%=mod;
            for(re int j=i+1;j<=m;j++)
                ans=(ans-quick(a[j]-a[i],m+1)%mod+mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

转载于:https://www.cnblogs.com/asuldb/p/10486069.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值