题目大意: 有 n n n 颗珍珠,现在给他们随机染色,颜色区间为 [ 1 , D ] [1,D] [1,D],两个颜色相同的珍珠可以装一瓶,现在问有多少种情况可以装至少 m m m 瓶?
题解
有一个比较显然的结论:假如有 k k k 个颜色出现奇数次,那么能装的瓶数就是 ⌊ n − k 2 ⌋ \left\lfloor \dfrac {n-k} 2 \right\rfloor ⌊2n−k⌋。
由于要求 ⌊ n − k 2 ⌋ ≥ m \left\lfloor \dfrac {n-k} 2 \right\rfloor \geq m ⌊2n−k⌋≥m,所以 n − k ≥ 2 m n-k\geq 2m n−k≥2m,即 k ≤ n − 2 m k\leq n-2m k≤n−2m。
显然可以特判两种情况: 2 m > n 2m>n 2m>n 时答案为 0 0 0, D ≤ n − 2 m D\leq n-2m D≤n−2m 时答案为 D n D^n Dn。
设
f
i
f_i
fi 表示至少有
i
i
i 种颜色出现了奇数次,
g
i
g_i
gi 表示恰好有
i
i
i 种颜色出现了奇数次,那么有:
f
i
=
∑
j
=
i
D
C
j
i
g
j
f_i=\sum_{j=i}^D C_j^i g_j
fi=j=i∑DCjigj
二项式反演一下得到:
g
i
=
∑
j
=
i
D
(
−
1
)
j
−
i
C
j
i
f
j
=
1
i
!
∑
j
=
i
D
(
−
1
)
j
−
i
(
j
−
i
)
!
×
f
j
j
!
\begin{aligned} g_i&=\sum_{j=i}^D (-1)^{j-i} C_j^i f_j\\ &=\frac 1 {i!}\sum_{j=i}^D \frac {(-1)^{j-i}} {(j-i)!} \times f_j j! \end{aligned}
gi=j=i∑D(−1)j−iCjifj=i!1j=i∑D(j−i)!(−1)j−i×fjj!
这是个卷积的形式,将 ( − 1 ) j − i ( j − i ) ! \dfrac {(-1)^{j-i}} {(j-i)!} (j−i)!(−1)j−i 翻转一下变成 ( − 1 ) D − j + i ( D − j + i ) ! \dfrac {(-1)^{D-j+i}} {(D-j+i)!} (D−j+i)!(−1)D−j+i,和后面的卷在一起得到第 D + i D+i D+i 位的值,然后将卷出来的数组左移 D D D 位得到 g i g_i gi。
所以求出 f f f 就能求出 g g g 了。那么下面的问题就是怎么求 f f f。
考虑对每个颜色构造
E
G
F
EGF
EGF,对于
f
k
f_k
fk 而言,至少有
k
k
k 个颜色出现奇数次,这些颜色的生成函数系数为
0
,
1
,
0
,
1
,
.
.
.
0,1,0,1,...
0,1,0,1,...,即
e
x
−
e
−
x
2
\frac {e^x-e^{-x}} 2
2ex−e−x,剩下的
n
−
k
n-k
n−k 种颜色随便取多少个,即
e
x
e^x
ex,那么有:
f
k
=
C
D
k
n
!
[
x
n
]
(
e
x
−
e
−
x
2
)
k
e
x
(
D
−
k
)
=
n
!
2
k
C
D
k
[
x
n
]
∑
j
=
0
k
C
k
j
e
j
x
(
−
e
−
x
)
(
k
−
j
)
e
x
(
D
−
k
)
=
n
!
2
k
C
D
k
∑
j
=
0
k
C
k
j
(
−
1
)
k
−
j
[
x
n
]
e
(
D
+
2
(
j
−
k
)
)
x
=
n
!
2
k
C
D
k
∑
j
=
0
k
C
k
j
(
−
1
)
k
−
j
(
D
+
2
j
−
2
k
)
n
n
!
=
n
!
D
!
k
!
(
D
−
k
)
!
2
k
∑
j
=
0
k
k
!
j
!
(
k
−
j
)
!
(
−
1
)
k
−
j
(
D
+
2
j
−
2
k
)
n
n
!
=
D
!
(
D
−
k
)
!
2
k
∑
j
=
0
k
(
D
−
2
(
k
−
j
)
)
n
(
−
1
)
k
−
j
(
k
−
j
)
!
×
1
j
!
\begin{aligned} f_k&=C_D^k n![x^n]\left(\frac {e^x-e^{-x}} 2\right)^k e^{x(D-k)}\\ &=\frac {n!} {2^k} C_D^k [x^n] \sum_{j=0}^k C_k^j e^{jx} (-e^{-x})^{(k-j)} e^{x(D-k)}\\ &=\frac {n!} {2^k} C_D^k \sum_{j=0}^k C_k^j (-1)^{k-j} [x^n]e^{(D+2(j-k))x}\\ &=\frac {n!} {2^k} C_D^k \sum_{j=0}^k C_k^j (-1)^{k-j} \frac {(D+2j-2k)^n} {n!}\\ &=\frac {n!D!} {k!(D-k)!2^k} \sum_{j=0}^k \frac {k!} {j!(k-j)!}(-1)^{k-j} \frac {(D+2j-2k)^n} {n!}\\ &=\frac {D!} {(D-k)!2^k} \sum_{j=0}^k \frac {(D-2(k-j))^n(-1)^{k-j}} {(k-j)!}\times \frac {1} {j!}\\ \end{aligned}
fk=CDkn![xn](2ex−e−x)kex(D−k)=2kn!CDk[xn]j=0∑kCkjejx(−e−x)(k−j)ex(D−k)=2kn!CDkj=0∑kCkj(−1)k−j[xn]e(D+2(j−k))x=2kn!CDkj=0∑kCkj(−1)k−jn!(D+2j−2k)n=k!(D−k)!2kn!D!j=0∑kj!(k−j)!k!(−1)k−jn!(D+2j−2k)n=(D−k)!2kD!j=0∑k(k−j)!(D−2(k−j))n(−1)k−j×j!1
发现后面又是个卷积的形式,卷一下答案就出来了。
代码如下:
#include <cstdio>
#include <algorithm>
using namespace std;
#define maxn 300010
#define mod 998244353
#define bin(x) (1<<(x))
int D,n,m;
int ksm(int x,int y){int re=1;for(;(y&1?re=1ll*re*x%mod:0),y;y>>=1,x=1ll*x*x%mod);return re;}
#define inv(x) ksm(x,mod-2)
int limit=1,l=0,r[maxn];
struct NTT{
int *w[30];NTT(){
for(int i=1,wn;i<=18;i++){
w[i]=new int[bin(i)];w[i][0]=1;wn=ksm(3,(mod-1)/bin(i));
for(int j=1;j<bin(i-1);j++)w[i][j]=1ll*w[i][j-1]*wn%mod;
}
}
void dft(int *f,int type=0)
{
if(type)reverse(f+1,f+limit);
for(int i=1;i<limit;i++)if(i<r[i])swap(f[i],f[r[i]]);
for(int mid=1,Lg=1;mid<limit;mid<<=1,Lg++)for(int j=0;j<limit;j+=(mid<<1))for(int i=0;i<mid;i++)
{int t=1ll*f[j+i+mid]*w[Lg][i]%mod;f[j+i+mid]=(f[j+i]-t+mod)%mod;f[j+i]=(f[j+i]+t)%mod;}
}
}ntt;
void FFT(int *f,int *g){
ntt.dft(f);ntt.dft(g);for(int i=0;i<limit;i++)f[i]=1ll*f[i]*g[i]%mod;
ntt.dft(f,1);for(int i=0,inv_l=inv(limit);i<limit;i++)f[i]=1ll*f[i]*inv_l%mod;
}
int fac[maxn],inv_fac[maxn],F[maxn],G[maxn];
int main()
{
scanf("%d %d %d",&D,&n,&m);
if(D<=n-2*m)return printf("%d",ksm(D,n)),0;
if(n<2*m)return printf("0"),0;
while(limit<=2*D+1)limit<<=1,l++;for(int i=0;i<limit;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
fac[0]=inv_fac[0]=1;for(int i=1;i<=maxn-10;i++)fac[i]=1ll*fac[i-1]*i%mod;
inv_fac[maxn-10]=inv(fac[maxn-10]);for(int i=maxn-11;i>=1;i--)inv_fac[i]=1ll*inv_fac[i+1]*(i+1)%mod;
for(int i=0;i<=D;i++)F[i]=1ll*ksm((D-2*i+mod)%mod,n)*(i&1?mod-inv_fac[i]:inv_fac[i])%mod,G[i]=inv_fac[i];FFT(F,G);
for(int i=0;i<=D;i++)F[i]=1ll*F[i]*fac[D]%mod*inv_fac[D-i]%mod*inv(ksm(2,i))%mod*fac[i]%mod;
for(int i=0;i<=D;i++)G[D-i]=(i&1?mod-inv_fac[i]:inv_fac[i]);for(int i=D+1;i<limit;i++)F[i]=G[i]=0;FFT(F,G);
int ans=0;for(int i=0;i<=n-2*m;i++)ans=(ans+1ll*F[i+D]*inv_fac[i]%mod)%mod;printf("%d",ans);
}