• 【洛谷6667】[清华集训2016] 如何优雅地求和(下降幂多项式)


    点此看题面

    • 有一个(m)次多项式(F(x)),给出它在(0sim m)(m+1)个点值。
    • 给定(n,x),求(sum_{k=0}^nF(k) imes C_n^k imes x^k imes(1-x)^{n-k})
    • (nle10^9,mle2 imes10^4)

    由点值到下降幂多项式

    (F(x))表示下降幂多项式系数的生成函数,(G(x))表示下降幂多项式点值的指数型生成函数,它们之间存在着一个很好的转化:(具体证明可见【洛谷5394】【模板】下降幂多项式乘法

    [F(x)=G(x)*e^{-x} ]

    这样一来我们就可以把给出的点值转化成下降幂多项式的形式,然后就可以开始愉快地推式子了。

    愉快地推式子

    在此之前可以先做做看【洛谷6620】[省选联考 2020 A 卷] 组合数问题(下降幂),算是此题的一个改编版。

    考虑我们现在已经求出了多项式(F(x)=sum_{i=0}^mf_ix^{underline{i}}),那么直接代入原式:

    [sum_{k=0}^nsum_{i=0}^mf_i imes k^{underline{i}} imes C_n^k imes x^k imes(1-x)^{n-k} ]

    看看(n,m)的范围,显然需要把(i)的枚举枚举提前,得到:

    [sum_{i=0}^mf_i imessum_{k=0}^nk^{underline{i}} imes C_n^k imes x^k imes(1-x)^{n-k} ]

    暴拆下降幂和组合数得到:

    [sum_{i=0}^mf_i imes sum_{k=0}^nfrac k{(k-i)!} imesfrac{n!}{k!(n-k)!} imes x^k imes(1-x)^{n-k}\ sum_{i=0}^mf_i imes sum_{k=0}^nfrac{n!}{(k-i)!(n-k)!} imes x^k imes(1-x)^{n-k} ]

    发现里面这坨组合数长得很丑陋,发现分母中((k-i)+(n-k)=n-i),因此我们把(n!)替换为((n-i)!),相当于提出来一个(n^{underline{i}})

    [sum_{i=0}^mf_i n^{underline{i}} imes sum_{k=0}^nC_{n-i}^{k-i} imes x^k imes (1-x)^{n-k} ]

    (k-i<0)的时候组合数没有意义,因此我们用(k+i)替换(k),得到:

    [sum_{i=0}^mf_i n^{underline{i}} imes sum_{k=0}^{n-i}C_{n-i}^{k} imes x^{k+i} imes (1-x)^{n-i-k}\ sum_{i=0}^mf_i n^{underline{i}}x^i imes sum_{k=0}^{n-i}C_{n-i}^{k} imes x^{k} imes (1-x)^{n-i-k} ]

    发现式子右边就是一个基本的二项式定理,就应该等于((x+1-x)^{n-i}=1)

    所以原式就是:

    [sum_{i=0}^mf_i n^{underline{i}}x^i ]

    这种东西随便算算就好了。

    代码:(O(mlogm))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define M 20000
    #define X 998244353
    using namespace std;
    int n,m,x,a[M+5],e[M+5],IFac[M+5];
    I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
    namespace Poly
    {
    	#define PR 3
    	int P,L,A[M<<2],B[M<<2],R[M<<2];I void T(int* s,CI op)
    	{
    		RI i,j,k,x,y,U,S;for(i=0;i^P;++i) i<R[i]&&(swap(s[i],s[R[i]]),0);
    		for(i=1;i^P;i<<=1) for(U=QP(QP(PR,op),(X-1)/(i<<1)),j=0;j^P;j+=i<<1) for(S=1,
    			k=0;k^i;++k,S=1LL*S*U%X) s[j+k]=((x=s[j+k])+(y=1LL*S*s[i+j+k]%X))%X,s[i+j+k]=(x-y+X)%X;
    	}
    	I void Mul(int* a,int* b)
    	{
    		RI i;P=1,L=0;W(P<=(m<<1)) P<<=1,++L;for(i=0;i^P;++i) R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
    		for(i=0;i<=m;++i) A[i]=a[i],B[i]=b[i];for(T(A,1),T(B,1),i=0;i^P;++i) A[i]=1LL*A[i]*B[i]%X;
    		RI t=QP(P,X-2);for(T(A,X-2),i=0;i<=m;++i) a[i]=1LL*A[i]*t%X;
    	}
    }
    int main()
    {
    	RI i;for(scanf("%d%d%d",&n,&m,&x),i=0;i<=m;++i) scanf("%d",a+i);
    	RI f=1;for(i=1;i<=m;++i) f=1LL*f*i%X;for(IFac[i=m]=QP(f,X-2);i;--i) IFac[i-1]=1LL*IFac[i]*i%X;//预处理阶乘逆元
    	for(i=0;i<=m;++i) a[i]=1LL*a[i]*IFac[i]%X,e[i]=(i&1)?X-IFac[i]:IFac[i];Poly::Mul(a,e);//由点值到下降幂多项式形式
    	RI t=0,p=1;for(f=1,i=0;i<=m;f=1LL*f*(n-i)%X,p=1LL*p*x%X,++i) t=(1LL*a[i]*p%X*f+t)%X;//计算答案式
    	return printf("%d
    ",t),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    如何选择数据科学最好的Python IDE?
    Python代码详解:入门时间序列分类
    2月编程语言排行榜:Python 稳坐前三,Java依旧第一
    写 Python 时的 5 个坏习惯
    Python的多线程threading和多进程multiprocessing
    Python看春运,万条拼车数据背后的春节迁徙地图
    python数据分析案例实战——融360客户贷款风险预测(信用卡)
    情人节攻略:用Python撒狗粮的正确姿势
    Python函数式编程
    python基础
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu6667.html
Copyright © 2020-2023  润新知