洛谷 P2791 幼儿园篮球题
https://www.luogu.org/problemnew/show/P2791
我喜欢唱♂跳♂rap♂篮球
要求的是:\(\sum_{i=0}^kC_m^iC_{n-m}^{k-i}i^L\)
这个\(i^L\)很烦,就把第二类斯特林数的式子套进去
\(\sum_{i=0}^kC_m^iC_{n-m}^{k-i}i^L\)
\(\sum_{i=0}^kC_m^iC_{n-m}^{k-i}\sum_{j=0}^iC_{i}^j\begin{Bmatrix}L\\j\end{Bmatrix}j!\)
\(\sum_{j=0}^k\begin{Bmatrix}L\\j\end{Bmatrix}j!\sum_{i=j}^kC_m^iC_{n-m}^{k-i}C_{i}^j\)
后面\(\sum\)三个组合数好像很不好搞,但是\(C_{m}^{i}C_{i}^{j}=C_{m}^{j}C_{m-j}^{i-j}\),可以拆出一个与\(i\)无关的组合数
\(\sum_{j=0}^k\begin{Bmatrix}L\\j\end{Bmatrix}j!C_{m}^{j}\sum_{i=j}^kC_{m-j}^{i-j}C_{n-m}^{k-i}\)
把式子化的好看一点,发现可以套范德蒙德卷积(\(\sum_{i=0}^kC_{n}^{i}C_{m}^{k-i}=C_{n+m}^k\))
\(\sum_{j=0}^k\begin{Bmatrix}L\\j\end{Bmatrix}j!C_{m}^{j}\sum_{i=0}^kC_{m-j}^{k-i-j}C_{n-m}^{i}\)
\(\sum_{j=0}^k\begin{Bmatrix}L\\j\end{Bmatrix}j!C_{m}^{j}C_{n-j}^{k-j}\)
注意上面循环\(i\)的上界实际上是\(\min(k,L,m)=O(L)\)
求出\(n=L\)的一行第二类斯特林数,每次询问就可以\(O(L)\)了
把组合数全拆出来约分就洛谷rk1了= =
#include<bits/stdc++.h> #define il inline #define vd void #define mod 998244353 #define poly std::vector<int> typedef long long ll; il ll gi(){ ll x=0,f=1; char ch=getchar(); while(!isdigit(ch))f^=ch=='-',ch=getchar(); while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return f?x:-x; } il int pow(int x,int y){ int ret=1; while(y){ if(y&1)ret=1ll*ret*x%mod; x=1ll*x*x%mod;y>>=1; } return ret; } #define maxn 524289 poly pA,pB; int rev[maxn],_lstN,P[maxn],iP[maxn]; il vd ntt(int*A,int N,int t){ for(int i=0;i<N;++i)if(rev[i]>i)std::swap(A[i],A[rev[i]]); for(int o=1;o<N;o<<=1){ int W=t?P[o]:iP[o]; for(int*p=A;p!=A+N;p+=o<<1) for(int i=0,w=1;i<o;++i,w=1ll*w*W%mod){ int t=1ll*w*p[i+o]%mod; p[i+o]=(p[i]-t+mod)%mod;p[i]=(p[i]+t)%mod; } } if(!t){ int inv=pow(N,mod-2); for(int i=0;i<N;++i)A[i]=1ll*A[i]*inv%mod; } } int N,lg; il vd setN(int n){ N=1,lg=0; while(N<n)N<<=1,++lg; if(N!=_lstN)for(int i=0;i<N;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<lg-1); } il vd ntt(poly&a,int t){ static int A[maxn]; for(int i=0;i<a.size();++i)A[i]=a[i];memset(A+a.size(),0,4*(N-a.size())); ntt(A,N,t); a.resize(N); for(int i=0;i<N;++i)a[i]=A[i]; int s=a.size();while(s&&!a[s-1])--s; a.resize(s); } il poly mul(poly a,poly b,int newn=-1){ if(newn==-1)newn=a.size()+b.size()-1; setN(a.size()+b.size()-1); ntt(a,1),ntt(b,1); for(int i=0;i<N;++i)a[i]=1ll*a[i]*b[i]%mod; ntt(a,0);a.resize(newn); return a; } il poly operator+(poly a,const poly&b){ if(a.size()<b.size())a.resize(b.size()); for(int i=0;i<a.size();++i)if(i<b.size())a[i]=(a[i]+b[i])%mod; return a; } il poly operator-(poly a,const poly&b){ if(a.size()<b.size())a.resize(b.size()); for(int i=0;i<a.size();++i)if(i<b.size())a[i]=(a[i]-b[i]+mod)%mod; return a; } il poly operator*(poly a,int b){ for(auto&i:a)i=1ll*i*b%mod; return a; } il poly qiudao(poly a){ for(int i=0;i<a.size()-1;++i)a[i]=1ll*a[i+1]*(i+1)%mod; a.erase(a.end()-1); return a; } il poly jifen(poly a){ a.insert(a.begin(),0); for(int i=1;i<a.size();++i)a[i]=1ll*a[i]*pow(i,mod-2)%mod; return a; } il poly getinv(poly a){ if(a.size()==1)return poly(1,pow(a[0],mod-2)); int n=a.size(),m=a.size()+1>>1; poly _a(m); for(int i=0;i<m;++i)_a[i]=a[i]; poly b=getinv(_a); setN(n+m*2-2); ntt(a,1);ntt(b,1); for(int i=0;i<N;++i)a[i]=1ll*a[i]*b[i]%mod*b[i]%mod; ntt(a,0),ntt(b,0); a.resize(n); return b*2-a; } il poly getln(poly a,int n=-1){ if(n==-1)n=a.size(); a.resize(n); return jifen(mul(qiudao(a),getinv(a),n)); } il poly getexp(poly a){ if(a.size()==1)return a[0]=1,a; int n=a.size(),m=a.size()+1>>1; poly _a(m); for(int i=0;i<m;++i)_a[i]=a[i]; poly b=getexp(_a); return mul(b,poly(1,1)-getln(b,a.size())+a,a.size()); } il poly operator^(poly a,int b){ int n=a.size(); a=getexp(getln(a)*b);a.resize(n); return a; } il poly sqrt(poly a){ if(a.size()==1)return a; int n=a.size(),m=a.size()+1>>1; poly _a(m); for(int i=0;i<m;++i)_a[i]=a[i]; poly b=sqrt(_a);b.resize(n); return (b+mul(a,getinv(b),n))*(mod+1>>1); } il vd poly_init(){ int G=3,iG=332748118; for(int i=1;i<maxn;i<<=1)P[i]=pow(G,(mod-1)/(i<<1)),iP[i]=pow(iG,(mod-1)/(i<<1)); } il vd add(int&a,int b){a=a+b>=mod?a+b-mod:a+b;} int fact[20000010],ifact[20000010]; int pr[4000010],Pr,PL[20000010]; bool yes[20000010]; int main(){ #ifdef XZZSB freopen("in.in","r",stdin); freopen("out.out","w",stdout); #endif poly_init(); int N=gi(),M=gi(),S=gi(),L=gi(),o=std::max(N,L); fact[0]=1;for(int i=1;i<=o;++i)fact[i]=1ll*i*fact[i-1]%mod; ifact[o]=pow(fact[o],mod-2);for(int i=o-1;~i;--i)ifact[i]=1ll*ifact[i+1]*(i+1)%mod; PL[0]=0,PL[1]=1; for(int i=2;i<=L;++i){ if(!yes[i])pr[++Pr]=i,PL[i]=pow(i,L); for(int j=1;j<=Pr&&i*pr[j]<=L;++j){ yes[i*pr[j]]=1; PL[i*pr[j]]=1ll*PL[pr[j]]*PL[i]%mod; if(i%pr[j]==0)break; } } poly f(L+1),g(L+1); for(int i=0,mul=1;i<=L;++i,mul=mod-mul)f[i]=1ll*mul*ifact[i]%mod; for(int i=0;i<=L;++i)g[i]=1ll*PL[i]*ifact[i]%mod; f=mul(f,g,L+1); while(S--){ int n=gi(),m=gi(),k=gi(),ans=0,o=std::min(k,std::min(m,L)); for(int i=0;i<=o;++i) ans=(ans+1ll*f[i]*ifact[m-i]%mod*fact[n-i]%mod*ifact[k-i])%mod; printf("%d\n",1ll*ans*fact[m]%mod*fact[k]%mod*ifact[n]%mod); } return 0; }
来源:https://www.cnblogs.com/xzz_233/p/11008759.html