CTS2019珍珠
不难发现我们需要一个选奇数/偶数个的egf
这个分别是 $\frac {e^x - e^{-x}} {2} $ 和 $\frac {e^x + e^{-x}} {2} $。
然后就可以开始推式子了。
答案是
\[n!\sum _{k=0}^{n-2m}(\frac {e^x + e^{-x}} {2}+y\frac {e^x - e^{-x}} {2})^D [x^n][y^k]
\]
\[= n! \frac {1}{2^D} \sum _{k=0}^{n-2m} \sum _{i=0}^D e^{(2i-D)x} (1+y)^i(1-y)^{D-i}[x^n][y^k]
\]
\[= \frac {1}{2^D} \sum_{i=0}^D \binom {D}{i}(2i-D)^n \sum _{k=0}^{n-2m} (1+y)^i(1-y)^{D-i}[y^k]
\]
好了,考虑如何计算这个东西。
首先将\((1-y)^D\)计算出来,因为$ (1+y)/(1-y) = 1 + 2y + 2y^2 + 2y^3 + ...$
设 \(lim = n-2m\)
我们可以轻易的算出贡献
枚举i, 枚举有多少次是2(至少多加了1)
有:
\[ans*2^D = \sum _{i=0}^D \binom {D}{i} (2i-D)^n \sum_p^D ff[p] \sum_{k=0}^D \binom {lim-p}{k} 2^k \binom{i}{k}
\]
交换第二三个和号,并且将只与一个变量相关的弄到一起,最后会形成如下形式:
\[ans*2^D = \sum _{i=0}^D A(i) \sum_p^D B(p) \frac{1}{(i-p)!}\sum_{k=0}^D C(k) \frac{1}{(lim-p-k)!}
\]
其中,\(A,B,C\)是三个多项式
将sigma_p后的部分当作f(p),f(p)可以通过C与\(e^x\)卷积得到,之后再卷积一次就能得出答案
复杂度一个log
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=998244353,g=3;
inline int add(int a,int b){a+=b;return a>=mod?a-mod:a;}
inline int sub(int a,int b){a-=b;return a<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline int qpow(int a,int b){int ret=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ret=mul(ret,a);return ret;}
const int inv2=qpow(2,mod-2);
/* math */
typedef vector<int> poly;
namespace poly_template{
int rev[4000010];
void DFT(int *t,int n,int type){
int l=0;while(1<<l<n)++l;
for(int i=1;i<n;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
for(int i=0;i<n;i++)if(i<rev[i])swap(t[i],t[rev[i]]);
for(int step=1;step<n;step<<=1){
int wn=qpow(g,(mod-1)/(step<<1));
for(int i=0;i<n;i+=step*2)for(int j=0,w=1;j<step;j++,w=mul(w,wn)){
int x=t[i+j],y=mul(w,t[i+j+step]);
t[i+j]=add(x,y),t[i+j+step]=sub(x,y);
}
}
if(type==1)return ;for(int i=1;i<n-i;i++)swap(t[i],t[n-i]);
int inv=qpow(n,mod-2);for(int i=0;i<n;i++)t[i]=mul(t[i],inv);
}
inline poly NTT(poly A,int n,poly B,int m){
poly ret;
int l=0;while(1<<l<n+m)++l;
A.resize(1<<l),B.resize(1<<l),ret.resize(1<<l);
DFT(&A[0],1<<l,1);DFT(&B[0],1<<l,1);
for(int i=0;i<1<<l;i++)ret[i]=mul(A[i],B[i]);
DFT(&ret[0],1<<l,-1);
ret.resize(n+m-1);
return ret;
}
inline poly NTT(poly A,poly B){return NTT(A,A.size(),B,B.size());}
}
using namespace poly_template;
int D,n,m;
int fac[4000010],ifac[4000010];
inline void binom_init(int n=4000000){
fac[0]=ifac[0]=1;for(int i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
ifac[n]=qpow(fac[n],mod-2);for(int i=n-1;i;i--)ifac[i]=mul(ifac[i+1],i+1);
}
inline int binom(int a,int b){
if(b>a)return 0;
return mul(fac[a],mul(ifac[b],ifac[a-b]));
}
poly G,ff,Fac,F;
int main()
{
binom_init();
cin >> D >> n >> m;
if(n<2*m){printf("%d\n",0);return 0;}
if(D<=n-2*m+1){printf("%d\n",qpow(D,n));return 0;}
ff.resize(D+1);G.resize(D+1);Fac.resize(D+1);F.resize(D+1);
int lim=n-2*m;
for(int i=0;i<=min(D,n-2*m);i++){
ff[i]=binom(D,i);
if(i&1)ff[i]=mod-ff[i];
ff[i]=mul(ff[i],fac[lim-i]);
}
for(int i=0;i<=D;i++)G[i]=mul(qpow(2,i),mul(ifac[i],ifac[i])), Fac[i]=ifac[i];
ff=NTT(ff,Fac);
for(int i=0;i<=D;i++)G[i]=mul(G[i],lim-i>=0?ff[lim-i]:0);
for(int i=0;i<=D;i++)F[i]=mul(mul(fac[D],ifac[D-i]),qpow(1ll*(mod+2*i-D)%mod,n));
G=NTT(Fac,G);
int ans=0;
for(int i=0;i<=D;i++){
ans=add(ans,mul(F[i],G[i]));
}
ans=mul(ans,qpow(inv2,D));
cout << ans << endl;
return 0;
}