UOJ #269. 【清华集训2016】如何优雅地求和

话说这题今年ZJOI讲课的时候lyx好像讲过,但是以当时姿势水平的我显然是看不懂的,所以现在来回头补一下

我们先来考虑一个简单的情况,\(f(k)=k\)时,我们可以得到:

\(Q=\sum_{k=0}^n k\times C_n^k\times x^k\times (1-x)^{n-k}\)

很显然为了化简后面的式子我们要凑出二项式定理的形式,同时这种推导在这里的P5591里已经推导过一遍了,就是用组合数吸收掉\(k\),因此最后就是\(Q=nx\)

但我们发现这个形式不够一般,但却能给我们一定的启发:前面的系数除了是\(k\)还能不能是别的可以通过组合数来吸收呢?

根据《具体数学》上的一些套路,我们发现下降阶乘幂有这个很好的性质,比如:我们令\(f(k)=k^{\underline d}\)时,则有:

\[Q=\sum_{k=0}^n k^{\underline d}\times C_n^k\times x^k\times (1-x)^{n-k} \]

\[=\sum_{k=0}^n k^{\underline d}\times \frac{n!}{k!(n-k)!}\times x^k\times (1-x)^{n-k} \]

\[=\sum_{k=0}^n n^{\underline d}x^d\times \frac{(n-d)!}{(k-d)!(n-k)!}\times x^{k-d}\times (1-x)^{n-k} \]

\[=n^{\underline d}x^d\times\sum_{k=0}^n C_{n-d}^{k-d}\times x^{k-d}\times (1-x)^{n-k} \]

所以后面还是一样的等于\(1\),因此这是\(Q=n^{\underline d} x^d\)

考虑最后答案的式子,我们显然发现对于\(f(k)=\sum_{i=0}^m a_i x^{\underline i}\),那么显然有\(Q(f,n,x)=\sum_{i=0}^m a_i\times Q(k^{\underline i},n,x)\)

根据前面的推导我们现在已经会做\(Q\)了,但是那个\(a_i\)该怎么求呢?

我们考虑设\(b_i=\frac{a_i}{i!}\),那么\(f(k)=\sum_{i=0}^m b_i\times C_x^i\)

考虑下降阶乘幂最好的朋友是谁,在《具体数学》中也有提到它就是差分(因为用来求不定和式的时候下降阶乘幂用处很大,而结合差分之后在离散数学中可以发挥和微积分类似的作用)

我们考虑我们现在知道的是\(k=0,1,\cdots,m\)\(f(k)\)的值,首先有\(k=0\)\(f(0)=b_0\)

然后我们记\(\Delta f(k)=f(k+1)-f(k)\),即它的一阶差分,因为组合数的基本性质\(C_{k+1}^i-C_k^i=C_k^{i-1}\),我们发现此时\(\Delta f(k)=\sum_{i=0}^m b_i\times C_k^{i-1}\),那么显然此时有\(\Delta f(0)=b_1\)

同理,我们容易推导出\(\Delta^d f(0)=b_d\),即\(d\)阶差分后\(0\)处的值为\(b_d\)

那么我们现在可以直接写出一个\(O(m^2)\)的暴力,再往后应该可以用NTT优化,但是由于这里数据范围不大,出题人写的也是\(O(m^2)\),因此我就懒了一下用暴力过了

#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
const int N=20005,mod=998244353;
int n,m,x,b[N],ans,ret=1,inv=1;
inline void inc(int& x,CI y)
{
	if ((x+=y)>=mod) x-=mod;
}
inline int sub(CI x,CI y)
{
	int t=x-y; return t<0?t+mod:t;
}
inline int quick_pow(int x,int p=mod-2,int mul=1)
{
	for (;p;p>>=1,x=1LL*x*x%mod) if (p&1) mul=1LL*mul*x%mod; return mul;
}
int main()
{
	RI i,j; for (scanf("%d%d%d",&n,&m,&x),i=0;i<=m;++i)
	scanf("%d",&b[i]); for (i=0;i<=m;++i)
	{
		if (i) inv=1LL*inv*quick_pow(i)%mod;
		inc(ans,1LL*ret*b[0]%mod*inv%mod);
		for (j=0;j<m-i;++j) b[j]=sub(b[j+1],b[j]);
		ret=1LL*ret*x%mod*(n-i)%mod;
	}
	return printf("%d",ans),0;
}
posted @ 2019-11-09 23:57  空気力学の詩  阅读(268)  评论(0编辑  收藏  举报