版权声明:写得不好,转载请通知一声,还请注明出处,感激不尽 https://blog.csdn.net/As_A_Kid/article/details/86698729
Problem
UOJ
给定
n,p ,
f(x)是一个
m 阶函数,求
Q(f)=k=0∑nf(k)(kn)pk(1−p)n−k(1)
Solution
首先
(−mn)=0
我们思考简单的二项分布即当
f(x)=x时的推导过程:
Q(f)=k=0∑nkk!(n−k)!n!pk(1−p)n−k(2)
Q(f)=k=0∑nn(k−1)!(n−k)!(n−1)!pk(1−p)n−k(3)
Q(f)=npk=0∑n(k−1n−1)pk−1(1−p)n−k(4)
Q(f)=npk=0∑n−1(kn−1)pk(1−p)n−k−1(5)
Q(f)=np(p+(1−p))n−1=np(6)
如法炮制,当
f(x)=xd时
Q(f)=ndpdk=0∑n−d(kn−d)pk(1−p)n−k=ndpd(7)
那么我们希望能求出
bi使得
f(x)=∑i=0mbixi,这样
Q(f)=∑i=0mbinipi
不妨令
ci=i!bi,那么
f(x)=i=0∑mcii!xi=i=0∑mci(ix)(8)
Δf(x)=f(x+1)−f(x)=i=0∑mci((ix+1)−(ix))=i=0∑mci(i−1x)(9)
取
x=0则仅有一个组合数为1,即
Δf(0)=c1。
然后一阶差分的式子和原来的式子惊人地相似,那么我们可以继续利用差分推出
Δkf(0)=ck
暴力差分的时间复杂度是
O(m2) ,这样就可以过了。但其实
k 阶差分是可以继续优化的,通过找规律,我们会发现
Δkf(0)=i=0∑k(−1)k−i(ik)ai(10)
NTT加速即可做到
O(mlogm)。
Code
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=20010,mod=998244353;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
int n,m,p,nd=1,pd=1,ans,a[maxn],b[maxn],fac[maxn],inv[maxn];
int pls(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
int power(int x,int y)
{
int res=1;
for(;y;y>>=1,x=(ll)x*x%mod)
if(y&1)
res=(ll)res*x%mod;
return res;
}
int main()
{
read(n);read(m);read(p);
for(int i=0;i<=m;i++) read(a[i]);
fac[0]=1;
for(int i=1;i<=m;i++) fac[i]=(ll)fac[i-1]*i%mod;
inv[m]=power(fac[m],mod-2);
for(int i=m-1;~i;i--) inv[i]=(ll)inv[i+1]*(i+1)%mod;
for(int i=0;i<=m;i++)
{
b[i]=(ll)a[0]*inv[i]%mod;
for(int j=0;j<m-i;j++) a[j]=dec(a[j+1],a[j]);
}
for(int i=0;i<=m;i++)
{
ans=pls(ans,(ll)b[i]*nd%mod*pd%mod);
nd=(ll)nd*(n-i)%mod;pd=(ll)pd*p%mod;
}
printf("%d\n",ans);
return 0;
}