• [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
    ",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
    */
    
  • 相关阅读:
    <mySql完全手册>2011031401
    <海量数据库解决方案>2011030801
    检索
    <mySql完全手册>2011022401
    <自己动手写操作系统>2011031601
    数据结构和算法基础
    <海量数据库解决方案>2011031001
    <自己动手写操作系统>2011032101
    Delphi方法类型
    .NET下的Login机制
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10373792.html
Copyright © 2020-2023  润新知