loj3120 「CTS2019 | CTSC2019」珍珠
.... 感觉自己太颓废了。。。。还是来更题解吧。。。【话说写博客会不会涨 rp 啊 qaq ?
题意:
有 n 个物品,每个都有一个 [1,D] 中随机的颜色,相同颜色的两个物品可以配对。现在要求至少能配 m 对,问方案数? $n,m\leq 10^9,D\leq 10^5$
题解:
配对数量 $\geq m \Longleftrightarrow$ 出现奇数次的权值个数 $\leq n-2m$ 。
一个权值出现偶数次的生成函数: $\frac{e^x +e^{-x}}{2}$
一个权值出现奇数次的生成函数: $\frac{e^x - e^{-x}}{2}$
答案的式子:
$$ \begin{aligned} &n!\sum_{k=0}^{n-2m} \left ( \frac{e^x +e^{-x}}{2} + y \frac{e^x - e^{-x}}{2} \right )^D [x^n][y^k]\\ =&n!\left (\frac12 \right )^D \sum_{k=0}^{n-2m} \left (e^x + e^{-x} + y\left ( e^x - e^{-x} \right )\right )^D[x^n][y^k]\\ =&n!\left (\frac12 \right )^D \sum_{k=0}^{n-2m} \left (e^x (1+y) + e^{-x}(1-y) \right )^D[x^n][y^k]\\ =&n!\left (\frac12 \right )^D \sum_{k=0}^{n-2m} \sum_{i=0}^{D}\binom{D}{i} \left (e^{x}(1+y) \right )^i \left( e^{-x}(1-y)\right )^{D-i} [x^n][y^k]\\ =&n!\left (\frac12 \right )^D \sum_{k=0}^{n-2m} \sum_{i=0}^{D}\binom{D}{i} e^{\left (2i-D\right )x} (1+y)^i (1-y)^{D-i} [x^n][y^k]\\ =&\left (\frac12 \right )^D \sum_{i=0}^{D} \binom{D}{i} (2i-D)^n \sum_{k=0}^{n-2m} (1+y)^i (1-y)^{D-i} [y^k] \end{aligned}$$
这就是最后的式子。
考虑怎么对于每个 i 快速求出后面的 $\sum_{k=0}^{n-2m} (1+y)^i (1-y)^{D-i} [y^k]$ ?
可以发现这是一个生成函数的系数前缀和。
即 $\left ( (1+y)^i (1-y)^{D-i} \right )\left (1+y+y^2+y^3+...\right ) [y^{n-2m}]$ ;
即 $\left ( (1+y)^i (1-y)^{D-i} \right )\left (\frac{1}{1-y}\right ) [y^{n-2m}]$ 。
可以发现当 $i\neq D$ 的时候,上式 $= \left ( (1+y)^i (1-y)^{D-i-1} \right )[y^{n-2m}]$ ;
$i=D$ 的时候上式 $=\sum_{k=0}^{n-2m} (1+y)^D [y^k]$ ,由于 $(1+y)^D$ 中 $y$ 不超过 D 次,所以有效的 $k\leq D$ ,暴力计算即可。
那 $i\neq D$ 的时候怎么办呢?我们记 $k=n-2m$ ,$d=D-1$ ,枚举两边对 k 的贡献,即
$$\sum_{j=0}^k \binom{i}{j} \binom{d-i}{k-j}(-1)^{k-j}$$
这种组合数的形式的转化当然是套路的阶乘展开啦——
$$\begin{aligned} \sum_{j=0}^k \frac{i!}{j!(i-j)!} \cdot \frac{(d-i)!}{(k-j)!(d-i-k+j)!} \cdot (-1)^{k-j}\\ =i!(d-i)!\sum_{j=0}^k \frac{(-1)^{k-j}}{j!(k-j)!} \cdot \frac{1}{(i-j)!(d-i-k+j)!}\\ \end{aligned}$$
就是个卷积形式了, fft 即可。
复杂度 $\mathcal{O}(D \log D).$
code:
1 #include<bits/stdc++.h> 2 #define rep(i,x,y) for (int i=(x);i<=(y);i++) 3 #define ll long long 4 5 using namespace std; 6 7 const int N=(1<<18)+10,mod=998244353,inv2=(mod+1)>>1; 8 int D,n,m,k,d,fac[N],ifac[N],ans,invn,w[N],r[N],a[N],b[N]; 9 10 int ksm(int x,int y){ 11 int s=1; x=(x+mod)%mod; 12 for (;y;y>>=1,x=(ll)x*x%mod) if (y&1) s=(ll)s*x%mod; 13 return s; 14 } 15 16 void init(int n){ 17 fac[0]=1; 18 rep (i,1,n) fac[i]=(ll)fac[i-1]*i%mod; 19 ifac[n]=ksm(fac[n],mod-2); 20 for (int i=n;i;i--) ifac[i-1]=(ll)ifac[i]*i%mod; 21 } 22 23 int C(int n,int m){ 24 if (n<m) return 0; 25 return (ll)fac[n]*ifac[m]%mod*ifac[n-m]%mod; 26 } 27 28 inline void upd(int &x,int y){x+=y; x-=x>=mod?mod:0;} 29 30 void fft_init(int &n){ 31 int len=0; while (1<<len<n) len++; n=1<<len; 32 int G=ksm(3,(mod-1)>>len); invn=ksm(n,mod-2); 33 w[0]=w[n]=1; 34 rep (i,1,n-1) w[i]=(ll)w[i-1]*G%mod,r[i]=(r[i>>1]>>1)|((i&1)<<(len-1)); 35 } 36 37 void fft(int *a,int all,int fl){ 38 rep (i,0,all-1) if (i<r[i]) swap(a[i],a[r[i]]); 39 int n=2,m=1,x=all>>1; 40 for (;n<=all;m=n,n<<=1,x>>=1) 41 for (int i=0;i<all;i+=n) 42 for (int k=0;k<m;k++){ 43 int t=(ll)w[fl?all-x*k:x*k]*a[i+m+k]%mod; 44 a[i+m+k]=(a[i+k]+mod-t)%mod; 45 a[i+k]=(a[i+k]+t)%mod; 46 } 47 if (fl) rep (i,0,all-1) a[i]=(ll)a[i]*invn%mod; 48 } 49 50 int main(){ 51 scanf("%d%d%d",&D,&n,&m),init(D); 52 k=min(n-2*m,D),d=D-1; 53 rep (i,0,k) a[i]=(ll)(((k-i)&1)?mod-1:1)%mod*ifac[i]%mod*ifac[k-i]%mod; 54 rep (i,0,d) if (d-k-i>=0) b[i]=(ll)ifac[i]%mod*ifac[d-k-i]%mod; 55 int _n=k+d+1; fft_init(_n); 56 fft(a,_n,0),fft(b,_n,0); 57 rep (i,0,_n-1) a[i]=(ll)a[i]*b[i]%mod; 58 fft(a,_n,1); 59 rep (i,0,d) a[i]=(ll)a[i]*fac[i]%mod*fac[d-i]%mod; 60 rep (i,0,D){ 61 int v=(ll)C(D,i)*ksm(2*i-D,n)%mod,tmp=0; 62 if (i==D) rep (i,0,k) upd(tmp,C(D,i)); 63 else tmp=a[i]; 64 upd(ans,(ll)tmp*v%mod); 65 } 66 printf("%lld\n",(ll)ans*ksm(inv2,D)%mod); 67 return 0; 68 }