[BZOJ3453]tyvj 1858 XLkxc:拉格朗日插值

分析

之前一直不知道拉格朗日插值是干什么用的,只会做模板题,做了这道题才明白这个神奇算法的用法。

由题意可知,\(f(x)\)是关于\(x\)\(k+1\)次函数,\(g(x)\)是关于\(x\)\(k+2\)次函数,\(ans(x)\)是关于\(x\)\(k+3\)次函数。

由于点值连续,插值可以做到\(O(n)\),求\(g(x)\)\(ans(x)\)都需要插值,因此时间复杂度为\(O(Tn^2 \log n)。(\)\log$是快速幂的,貌似可以通过预处理逆元优化掉,不过AC这道题已经绰绰有余了。

代码

#include <bits/stdc++.h>
#define rin(i,a,b) for(register int i=(a);i<=(b);++i)
#define irin(i,a,b) for(register int i=(a);i>=(b);--i)
#define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl;

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

const LL MOD=1234567891;
const int MAXN=130;

int k;
LL s,n,d,inv[MAXN],ff[MAXN],gg[MAXN],hh[MAXN];

inline LL qpow(LL x,LL y){
    LL ret=1,tt=x%MOD;
    while(y){
        if(y&1) ret=ret*tt%MOD;
        tt=tt*tt%MOD;
        y>>=1;
    }
    return ret;
}

LL g(LL x){
    if(x<=k+3) return gg[x];
    LL son=1,mot=1;
    rin(i,2,k+3) son=son*(x-i+MOD)%MOD;
    rin(i,2,k+3) mot=mot*(1-i+MOD)%MOD;
    LL ret=0;
    rin(i,1,k+3){
        ret=(ret+gg[i]*son%MOD*qpow(mot,MOD-2))%MOD;
        son=son*qpow(x-(i+1)+MOD,MOD-2)%MOD*(x-i+MOD)%MOD;
        mot=mot*qpow(k+3-i+MOD,MOD-2)%MOD*(MOD-i)%MOD;
    }
    return ret;
}

LL h(LL x){
    if(x<=k+4) return hh[x];
    LL son=1,mot=1;
    rin(i,2,k+4) son=son*(x-i+MOD)%MOD;
    rin(i,2,k+4) mot=mot*(1-i+MOD)%MOD;
    LL ret=0;
    rin(i,1,k+4){
        ret=(ret+hh[i]*son%MOD*qpow(mot,MOD-2))%MOD;
        son=son*qpow(x-(i+1)+MOD,MOD-2)%MOD*(x-i+MOD)%MOD;
        mot=mot*qpow(k+4-i+MOD,MOD-2)%MOD*(MOD-i)%MOD;
    }
    return ret;
}

int main(){
    int T=read();
    while(T--){
        k=read(),s=read(),n=read(),d=read();
        ff[0]=0;
        rin(i,1,k+3) ff[i]=(ff[i-1]+qpow(i,k))%MOD;
        gg[0]=0;
        rin(i,1,k+3) gg[i]=(gg[i-1]+ff[i])%MOD;
        hh[0]=g(s);
        rin(i,1,k+4) hh[i]=(hh[i-1]+g((s+i*d)%MOD))%MOD;
        printf("%lld\n",h(n));
    }
    return 0;
}

/*
5
120 102497463 92989700 20360484
66 105420730 97423975 32388530
95 64109604 78460286 106343540
101 66688000 92566071 49084899
102 120568505 7166048 11911911

948519230
179937457
690200633
382076592
500116309
*/

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/10373792.html
0条评论
添加一条新回复