1 条题解
-
0
自动搬运
来自洛谷,原作者为

λᴉʍ
大家好,我是刚学OI的萌新搬运于
2025-08-24 21:41:40,当前版本为作者最后更新于2019-06-12 11:55:14,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
我喜欢唱♂跳♂rap♂篮球
要求的是:
这个很烦,就把第二类斯特林数的式子套进去
$\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_{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_{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}$
注意上面循环的上界实际上是
求出的一行第二类斯特林数,每次询问就可以了
把组合数全拆出来约分就洛谷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; }
- 1
信息
- ID
- 4338
- 时间
- 2000ms
- 内存
- 512MiB
- 难度
- 7
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者