背景:
律师函警告。
另外
yyb
\text{yyb}
yyb太巨了,解锁了新姿势。
题目传送门:
https://www.luogu.org/problem/P2791
题意:
N
N
N个球,其中
M
M
M个没气的;每一次
cxk’s fans
\text{cxk's fans}
cxk’s fans从中选出
n
n
n个球,其中
m
m
m个没气的;而
cxk
\text{cxk}
cxk每次会从这
n
n
n个球中选出
k
k
k个球,其中每一次没气的球的个数
x
x
x会产生
x
k
x^k
xk的贡献,求最后的总期望。
思路:
考虑
a
n
s
ans
ans的表示,
i
i
i枚举
cxk
\text{cxk}
cxk选出的没气的球,很容易有下面的式子,不解释了,
cxk
\text{cxk}
cxk水平。
a
n
s
=
C
M
m
C
N
−
M
n
−
m
∑
i
=
0
k
C
m
i
C
n
−
m
k
−
i
i
L
C
M
m
C
N
−
M
n
−
m
ans=\frac{C_{M}^{m}C_{N-M}^{n-m}\sum_{i=0}^{k}C_{m}^{i}C_{n-m}^{k-i}i^L}{C_{M}^{m}C_{N-M}^{n-m}}
ans=CMmCN−Mn−mCMmCN−Mn−m∑i=0kCmiCn−mk−iiL
我们知道
i
L
=
∑
j
=
0
L
S
L
,
j
C
i
j
j
!
i^L=\sum_{j=0}^{L}S_{L,j}C_{i}^{j}j!
iL=∑j=0LSL,jCijj!,带入可得:
a
n
s
=
∑
i
=
0
k
C
m
i
C
n
−
m
k
−
i
∑
j
=
0
L
S
L
,
j
C
i
j
j
!
ans=\sum_{i=0}^{k}C_{m}^{i}C_{n-m}^{k-i}\sum_{j=0}^{L}S_{L,j}C_{i}^{j}j!
ans=i=0∑kCmiCn−mk−ij=0∑LSL,jCijj!
a n s = ∑ i = 0 k C m i C n − m k − i ∑ j = 0 L S L , j C i j j ! j ! ans=\sum_{i=0}^{k}C_{m}^{i}C_{n-m}^{k-i}\sum_{j=0}^{L}S_{L,j}C_{i}^{j}j!j! ans=i=0∑kCmiCn−mk−ij=0∑LSL,jCijj!j!
a n s = ∑ j = 0 L S L , j j ! ∑ i = 0 k C m i C n − m k − i C i j ans=\sum_{j=0}^{L}S_{L,j}j!\sum_{i=0}^{k}C_{m}^{i}C_{n-m}^{k-i}C_{i}^{j} ans=j=0∑LSL,jj!i=0∑kCmiCn−mk−iCij
搞到这里不会了啊,式子化简不出来,膜题解吧。
a
n
s
=
∑
j
=
0
L
S
L
,
j
j
!
∑
i
=
0
k
m
!
i
!
(
m
−
i
)
!
C
n
−
m
k
−
i
i
!
j
!
(
i
−
j
)
!
ans=\sum_{j=0}^{L}S_{L,j}j!\sum_{i=0}^{k}\frac{m!}{i!(m-i)!}C_{n-m}^{k-i}\frac{i!}{j!(i-j)!}
ans=j=0∑LSL,jj!i=0∑ki!(m−i)!m!Cn−mk−ij!(i−j)!i!
a n s = ∑ j = 0 L S L , j j ! ∑ i = 0 k m ! ( m − i ) ! 1 j ! ( i − j ) ! C n − m k − i ans=\sum_{j=0}^{L}S_{L,j}j!\sum_{i=0}^{k}\frac{m!}{(m-i)!}\frac{1}{j!(i-j)!}C_{n-m}^{k-i} ans=j=0∑LSL,jj!i=0∑k(m−i)!m!j!(i−j)!1Cn−mk−i
a n s = ∑ j = 0 L S L , j j ! ∑ i = 0 k m ! ( m − i ) ! ( m − j ) ! ( m − j ) ! j ! ( i − j ) ! C n − m k − i ans=\sum_{j=0}^{L}S_{L,j}j!\sum_{i=0}^{k}\frac{m!}{(m-i)!(m-j)!}\frac{(m-j)!}{j!(i-j)!}C_{n-m}^{k-i} ans=j=0∑LSL,jj!i=0∑k(m−i)!(m−j)!m!j!(i−j)!(m−j)!Cn−mk−i
a n s = ∑ j = 0 L S L , j j ! ∑ i = 0 k m ! j ! ( m − j ) ! ( m − j ) ! ( m − i ) ! ( i − j ) ! C n − m k − i ans=\sum_{j=0}^{L}S_{L,j}j!\sum_{i=0}^{k}\frac{m!}{j!(m-j)!}\frac{(m-j)!}{(m-i)!(i-j)!}C_{n-m}^{k-i} ans=j=0∑LSL,jj!i=0∑kj!(m−j)!m!(m−i)!(i−j)!(m−j)!Cn−mk−i
a n s = ∑ j = 0 L S L , j j ! ∑ i = 0 k C m j C m − j i − j C n − m k − i ans=\sum_{j=0}^{L}S_{L,j}j!\sum_{i=0}^{k}C_{m}^{j}C_{m-j}^{i-j}C_{n-m}^{k-i} ans=j=0∑LSL,jj!i=0∑kCmjCm−ji−jCn−mk−i
a n s = ∑ j = 0 L S L , j m ! ( m − j ) ! ∑ i = 0 k C m − j i − j C n − m k − i ans=\sum_{j=0}^{L}S_{L,j}\frac{m!}{(m-j)!}\sum_{i=0}^{k}C_{m-j}^{i-j}C_{n-m}^{k-i} ans=j=0∑LSL,j(m−j)!m!i=0∑kCm−ji−jCn−mk−i
考虑范德蒙恒等式
∑
i
=
0
k
C
m
−
j
i
−
j
C
n
−
m
k
−
i
=
C
n
−
j
k
−
j
\sum_{i=0}^{k}C_{m-j}^{i-j}C_{n-m}^{k-i}=C_{n-j}^{k-j}
∑i=0kCm−ji−jCn−mk−i=Cn−jk−j,有:
a
n
s
=
∑
j
=
0
L
S
L
,
j
m
!
(
m
−
j
)
!
C
n
−
j
k
−
j
ans=\sum_{j=0}^{L}S_{L,j}\frac{m!}{(m-j)!}C_{n-j}^{k-j}
ans=j=0∑LSL,j(m−j)!m!Cn−jk−j
a n s = ∑ j = 0 L S L , j m ! ( m − j ) ! ( n − j ) ! ( k − j ) ! ( n − k ) ! ans=\sum_{j=0}^{L}S_{L,j}\frac{m!}{(m-j)!}\frac{(n-j)!}{(k-j)!(n-k)!} ans=j=0∑LSL,j(m−j)!m!(k−j)!(n−k)!(n−j)!
a
n
s
=
m
!
(
n
−
k
)
!
∑
j
=
0
L
S
L
,
j
1
(
m
−
j
)
!
(
n
−
j
)
!
(
k
−
j
)
!
ans=\frac{m!}{(n-k)!}\sum_{j=0}^{L}S_{L,j}\frac{1}{(m-j)!}\frac{(n-j)!}{(k-j)!}
ans=(n−k)!m!j=0∑LSL,j(m−j)!1(k−j)!(n−j)!
预处理第二类斯特林数,就可以
Θ
(
L
)
\Theta(L)
Θ(L)出解了。
总时间复杂度:
Θ
(
n
+
L
log
L
+
S
L
)
\Theta(n+L\log L+SL)
Θ(n+LlogL+SL),挺大的。
卡常警告。
[
1
]
[1]
[1]:
i
L
i^L
iL可以用线性筛处理,避免快速幂的
log
\text{log}
log;
[
2
]
[2]
[2]:不要用逆元的前缀积来算阶乘的逆元,选择先算出最大的阶乘的逆元,每一次再乘
i
+
1
i+1
i+1推过去,快了好多。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define I inline
#define R register
#define mod 998244353
using namespace std;
int r[600010],f[600010],g[600010],w[600010],prime[200010],Pow[200010],fac[20000010],Inv[20000010];
int S,L,n,m,k,limit,l,ans;
I int ksm(int x,int k)
{
int tot=1;
for(;k;k>>=1)
{
if(k&1) tot=(LL)tot*x%mod;
x=(LL)x*x%mod;
}
return tot;
}
I void NTT(int *now,int limit,int n,int op)
{
for(R int i=0;i<limit;++i)
if(i<r[i]) std::swap(now[i],now[r[i]]);
for(R int mid=1;mid<limit;mid<<=1)
{
int wn=ksm(op==1?3:332748118,(mod-1)/(mid<<1));
w[0]=1;
for(R int k=1;k<mid;k++)
w[k]=(LL)w[k-1]*wn%mod;
for(R int j=0;j<limit;j+=(mid<<1))
for(R int k=0;k<mid;++k)
{
int x=now[j+k],y=(LL)w[k]*now[j+k+mid]%mod;
now[j+k]=(x+y)%mod;
now[j+k+mid]=(x-y+mod)%mod;
}
}
if(op==1) return;
int INV=ksm(limit,mod-2);
for(R int i=0;i<n;++i)
f[i]=(LL)f[i]*INV%mod;
}
I void Init()
{
int ma=std::max(n,L);
fac[0]=fac[1]=Inv[0]=Inv[1]=1;
for(R int i=2;i<=ma;++i)
fac[i]=(LL)fac[i-1]*i%mod;
Inv[ma]=ksm(fac[ma],mod-2);
for(R int i=ma-1;i;i--)
Inv[i]=(LL)Inv[i+1]*(i+1)%mod;
int t=0;
Pow[1]=1;
for(R int i=2;i<=L;++i)
{
if(!Pow[i]) Pow[i]=ksm(i,L),prime[++t]=i;
for(R int j=1;j<=t&&i*prime[j]<=L;++j)
{
Pow[i*prime[j]]=(LL)Pow[i]*Pow[prime[j]]%mod;
if(!(i%prime[j])) break;
}
}
for(R int i=0;i<=L;++i)
{
f[i]=(i&1)?mod-Inv[i]:Inv[i];
g[i]=(LL)Pow[i]*Inv[i]%mod;
}
limit=1,l=0;
++L;
while(limit<(L<<1))
limit<<=1,++l;
for(R int i=1;i<limit;++i)
r[i]=((r[i>>1]>>1)|((i&1)<<(l-1)));
NTT(f,limit,L,1),NTT(g,limit,L,1);
for(R int i=0;i<limit;++i)
f[i]=(LL)f[i]*g[i]%mod;
NTT(f,limit,L,-1);
--L;
}
I int read()
{
int x=0,f=1;
char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar());
for(;ch>='0'&&ch<='9';x=(x<<3)+(x<<1)+(ch^48),ch=getchar());
return x*f;
}
void print(int x)
{
if(x>9) print(x/10);
putchar(x%10+'0');
}
int main()
{
int mi;
n=read(),m=read(),S=read(),L=read();
Init();
for(R int j=1;j<=S;++j)
{
ans=0;
n=read(),m=read(),k=read();
mi=std::min(std::min(k,m),L);
for(R int i=1;i<=mi;++i)
ans=(ans+(LL)f[i]*Inv[m-i]%mod*fac[n-i]%mod*Inv[k-i]%mod)%mod;
print((LL)fac[m]*fac[k]%mod*Inv[n]%mod*ans%mod),puts("");
}
}