Luo Gu [2791] (Stirling numbers of second kind, NTT) Kindergarten basketball title
Face questions
answer
For each set of query, the things essential requirement is that:
\ [\ sum_ {I} = 0 {K} ^ {m \ I} the Choose {\ I} the Choose nm Ki ^ L \]
that if there is no back section, is a Vandermonde's identity, so it is imperative that \ (i ^ L \) is directly removed.
Take then directly to the second split Stirling Number:
\ [I ^ L = \ sum_ J = {0} L ^ \ bmatrix the begin {L} \\ J \ bmatrix End {} {I \} the Choose J J! \]
then put split into answer:
\ [\ the aligned the begin {} & Ans = \ sum_ {I} = 0 {m ^ K \ I the Choose {nm} \} the Choose Ki = I ^ & \\ L \ sum_ { i = 0} ^ {k} {m \ choose i} {nm \ choose ki} \ sum_ {j = 0} ^ L \ begin {bmatrix} L \\ j \ end {bmatrix} {i \ choose j} j ! \\ & = \ sum_ {j = 0} ^ L \ begin {bmatrix} L \\ j \ end {bmatrix} j! \ sum_ ^ {k} {m \ choose i} {nm {i 0 =} \ choose ki} {i \ choose j
} \ end {aligned} \] and found \ (\ displaystyle {m \ choose
i} {i \ choose j} = {m \ choose j} {mj \ choose ij} \) then there:
\ [\ begin {aligned} Ans & = \ sum_ {j = 0} ^ L \ begin {Bmatrix} L \\ j \ end {Bmatrix} j! {m \ choose j} \ sum_ {i = 0} ^ {k } {nm \ choose ki} { mj \ choose ij} \\ & = \ sum_ {j = 0} ^ L \ begin {bmatrix} L \\ j \ end {bmatrix} j! {m \ choose j} {nj \ choose kj} \\ \ end {
aligned} \] this way can be done single \ (O (L) \) .
Thus the number of the second type Stirling pretreatment on the line.
This problem often do not know why the card, the card often do not understand the significance of fit in ......
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MOD 998244353
#define MAX 524288
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
int W[MAX],r[MAX];
void NTT(int *P,int opt,int len)
{
int l=0,N;for(N=1;N<len;N<<=1)++l;
for(int i=0;i<N;++i)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
for(int i=0;i<N;++i)if(i<r[i])swap(P[i],P[r[i]]);
for(int i=1;i<N;i<<=1)
{
int w=fpow(3,(MOD-1)/(i<<1));W[0]=1;
for(int k=1;k<i;++k)W[k]=1ll*W[k-1]*w%MOD;
for(int j=0,p=i<<1;j<N;j+=p)
for(int k=0;k<i;++k)
{
int X=P[j+k],Y=1ll*W[k]*P[i+j+k]%MOD;
P[j+k]=(X+Y)%MOD;P[i+j+k]=(X+MOD-Y)%MOD;
}
}
if(opt==-1)
{
reverse(&P[1],&P[N]);
for(int i=0,inv=fpow(N,MOD-2);i<N;++i)P[i]=1ll*P[i]*inv%MOD;
}
}
int n,m,T,L;
int A[MAX],B[MAX],S[MAX];
int jc[20000010],jv[20000010];
int C(int n,int m){if(n<m||n<0||m<0)return 0;return 1ll*jc[n]*jv[m]%MOD*jv[n-m]%MOD;}
int main()
{
n=read();m=read();T=read();L=read();
jc[0]=jv[0]=jv[1]=1;int mx=max(L,n);
for(int i=1;i<=mx;++i)jc[i]=1ll*jc[i-1]*i%MOD;jv[mx]=fpow(jc[mx],MOD-2);
for(int i=mx-1;i;--i)jv[i]=1ll*jv[i+1]*(i+1)%MOD;
for(int i=0,d=1;i<=L;++i,d=MOD-d)A[i]=1ll*d*jv[i]%MOD;
for(int i=0;i<=L;++i)B[i]=1ll*fpow(i,L)*jv[i]%MOD;
int N;for(N=1;N<=L+L;N<<=1);
NTT(A,1,N);NTT(B,1,N);
for(int i=0;i<N;++i)S[i]=1ll*A[i]*B[i]%MOD;
NTT(S,-1,N);
while(T--)
{
int N=read(),M=read(),K=read(),ans=0,Lim=min(L,min(M,min(N,K)));;
for(int i=0;i<=Lim;++i)ans=(ans+1ll*S[i]*jv[M-i]%MOD*jc[N-i]%MOD*jv[K-i])%MOD;
ans=1ll*ans*jc[M]%MOD*jv[N]%MOD*jc[K]%MOD;
printf("%d\n",ans);
}
return 0;
}