洛谷ios
對於每一組詢問,要求的東西本質上就是:
\[\sum_{i=0}^{k}{m\choose i}{n-m\choose k-i}i^L\]
若是沒有後面那個部分,就是一個範德蒙恆等式,因此就要把這個\(i^L\)直接拆掉。
而後直接拿第二類斯特林數來拆:
\[i^L=\sum_{j=0}^L\begin{Bmatrix}L\\j\end{Bmatrix}{i\choose j}j!\]
因而就把答案拆成了:
\[\begin{aligned} Ans&=\sum_{i=0}^k{m\choose i}{n-m\choose k-i}i^L\\ &=\sum_{i=0}^{k}{m\choose i}{n-m\choose k-i}\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_{i=0}^{k}{m\choose i}{n-m\choose k-i}{i\choose j} \end{aligned}\]
而後發現\(\displaystyle {m\choose i}{i\choose j}={m\choose j}{m-j\choose i-j}\)
而後就有:
\[\begin{aligned} Ans&=\sum_{j=0}^L\begin{Bmatrix}L\\j\end{Bmatrix}j!{m\choose j}\sum_{i=0}^{k}{n-m\choose k-i}{m-j\choose i-j}\\ &=\sum_{j=0}^L\begin{Bmatrix}L\\j\end{Bmatrix}j!{m\choose j}{n-j\choose k-j}\\ \end{aligned}\]
這樣子能夠作到單次\(O(L)\)。
因而預處理第二類斯特林數就好了。
這題不知道爲何要卡常,不太理解卡常的意義合在......spa
#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; }