• BZOJ.3453.tyvj 1858 XLkxc(拉格朗日插值)


    BZOJ

    题意即求$$sum_{i=0}^nsum_{j=1}^{a+id}sum_{x=1}^jx^k$$

    我们知道最后一个(sum)是自然数幂和,设(f(n)=sum_{x=1}^nx^k),这是一个(k+1)次多项式,可以插值求出(当然本题只需要求出任意(k+3)个值即可不需要插值)。
    (g(n)=sum_{i=1}^nf(i)),(打表)差分可知这是一个(k+2)次多项式。
    同样令(h(n)=sum_{i=0}^ng(a+id)),同样差分可知这是一个(k+3)次多项式。
    所以用拉格朗日插值我们代入(k+4)个值就可以求出(h(n))了。

    也就是先求(k+3)(f(x))的值,再求出(k+3)(g(x))的值,然后对(g)插值求(k+4)(g(a+xd)),前缀和一下就有了(h)(k+4)个值,然后再插一次就得到(h(n))了。(嵌套好鬼畜...)


    注意(f,g,h)都是个前缀和...
    注意这题两倍的模数会爆int。可以用unsigned int


    从这题可以看出:

    1. 多一个(sum)一般会使多项式次数+1。
    2. 插值可以嵌套,且复杂度不变,仍是(O(k^2))

    这是伯努利数的做法:https://blog.csdn.net/qq_20669971/article/details/65938763。


    //824kb	28ms
    #include <cstdio>
    #include <algorithm>
    #define mod 1234567891
    #define Mod(x) x>=mod&&(x-=mod)
    #define Add(x,v) (x+=v)>=mod&&(x-=mod)
    typedef long long LL;
    typedef unsigned int uint;
    const int N=130;
    
    uint g[N],h[N],ifac[N];
    
    inline uint FP(uint x,uint k)
    {
    	uint t=1;
    	for(; k; k>>=1,x=1ll*x*x%mod)
    		if(k&1) t=1ll*t*x%mod;
    	return t;
    }
    uint Lagrange(uint *y,const int m,uint x)
    {
    	static uint pre[N],suf[N];
    	pre[0]=x, suf[m+1]=1;
    	for(int i=1; i<m; ++i) pre[i]=1ll*pre[i-1]*(x+mod-i)%mod;
    	for(int i=m; i; --i) suf[i]=1ll*suf[i+1]*(x+mod-i)%mod;
    	LL ans=0;
    	for(int i=0,up,down; i<=m; ++i)
    	{
    		if(i) up=1ll*pre[i-1]*suf[i+1]%mod*y[i]%mod;
    		else up=1ll*suf[i+1]*y[i]%mod;
    		down=(m-i)&1?mod-1ll*ifac[i]*ifac[m-i]%mod:1ll*ifac[i]*ifac[m-i]%mod;
    		ans+=1ll*up*down%mod;
    	}
    	return ans%mod;
    }
    
    int main()
    {
    	ifac[N-1]=1119688141;//是129!的逆元不是129的!!!今天错了两次这个真是醉了=-= 
    	for(int i=N-1; i; --i) ifac[i-1]=1ll*ifac[i]*i%mod;
    
    	int T,K; uint a,n,d; g[0]=0;
    	for(scanf("%d",&T); T--; )
    	{
    		scanf("%d%u%u%u",&K,&a,&n,&d);
    		for(int i=1; i<=K+2; ++i) g[i]=g[i-1]+FP(i,K), Mod(g[i]); //f = sum i^k
    		for(int i=1; i<=K+2; ++i) Add(g[i],g[i-1]); //g = sum f(i)
    		h[0]=Lagrange(g,K+2,a);
    		for(int i=1; i<=K+3; ++i) Add(a,d), h[i]=h[i-1]+Lagrange(g,K+2,a), Mod(h[i]);
    		printf("%d
    ",(int)Lagrange(h,K+3,n));
    	}
    	return 0;
    }
    
  • 相关阅读:
    从零开始搭建Wpf基础9-使用MaterialDesignToolkit对界面进行美化下
    从零开始搭建Wpf基础8-登录界面成功后显示主窗体
    从零开始搭建Wpf基础7-Api数据接入
    从零开始搭建Wpf基础6-Tab选项卡MVVM实现
    Wpf下dragablz使用Prism8进行导航-3
    从零开始搭建Wpf基础5-无限级菜单MVVM实现
    从零开始搭建Wpf基础篇4-使用Prism进行模块化
    从零开始搭建Wpf初学篇3-界面模块化
    手写es5和es6实现原型继承
    判断类型(通用类型检测方法)和手写深拷贝
  • 原文地址:https://www.cnblogs.com/SovietPower/p/10244452.html
Copyright © 2020-2023  润新知