CF Round#698 Div1.
Nezzar and Chocolate Bars
前言
这就是大道至简吗。。
为什么和某ZJOI开关一样,到最后就是个背包。。
题目大意:
给定 \(n,K\) 和一些棍子长度为 \(l_i(i\in [1,n])\) (实数!)
每次随机选择一根棍子,概率与 \(l_i\)
成正比,然后随机分裂成两段(实数!)
一直分裂,直到每根棍子 \(l_i\leq K\)
,求期望分裂次数
\[ \ \]
根据题意容易归纳一个更直观的模型:
把这些 \(l_i\)
排在数轴上,初始时,点集为 \(0,l_1,l_1+l_2,\ldots\)
每次随机在数轴上撒一个点,直到点集中相邻两点距离 \(\leq K\) 为止
考虑从简单情况入手
\[ \ \]
n=1
单棍情况,设长度为 \(L\)
,考虑期望的简单等价变换
\(\displaystyle
E(\text{条件第一次成立操作数})=\sum_{i=0}^{\infty}
P(i次操作条件未成立)\)
设 \(P_n\) 为操作 \(n\) 次成立(不是恰好)的概率
(变量名重了不要介意)
设 \(n\) 次操作后的点集排列之后为
\(X_i\) ,其中 \(X_0=0,X_{n+1}=L\)
我们要求 \(\forall
i\in[1,n+1],Z_i=X_i-X_{i-1}\leq K\)
,考虑用一个二项式反演来解决这个计算
设 \(W=\lfloor
\frac{L}{K}\rfloor\)
\(\displaystyle
P_n=\frac{1}{L^n}\sum_{i=0}^{W}
(-1)^i\binom{n+1}{i}(L-iK)^n\)
其意义即为从分成的 \(n+1\) 个 \(Z_i\) 中选择 \(i\)
个强制不合法,然后剩下的随意分布,由此计算概率
\[ \ \]
一般情形
考虑一样的期望转概率,设 \(p_m\) 为
\(m\) 次完成的概率, \(q_m=1-p_m\)
\(\displaystyle q_m=\sum_{j_1+j_2+\cdots
+j_n=m} \frac{m!}{j_1!j_2!\cdots j_n!}\prod (\frac{l_i}{\sum
l_k})^{j_i}P_{i,j_i}\)
显然这里考虑用 \(\text{EGF}\)
积的形式来表示,设 \(S=\sum l_i\)
回到上一步,这里我们对于 \(i,l_i\)
计算其 \(P_n\) 加上 \(\frac{l_i}{S}\) 系数的 \(\text{EGF}\) ,沿用上面的 \(L=l_i\)
\(\displaystyle
F_i(x)=\text{EGF(P)}=\sum_{n\ge
0}\frac{1}{n!}(\frac{L}{S})^n\sum_{i=0}^W(-1)^{i}\binom{n+1}{i}(1-i\frac{K}{L})^{n}x^n\)
\(\displaystyle F_i(x)=\sum_{n\ge
0}\frac{1}{n!}\sum_{i=0}^W(-1)^{i}\binom{n+1}{i}(\frac{L-iK}{S})^{n}x^n\)
设 \(\displaystyle
u=\frac{L-iK}{S}x\)
\(\displaystyle
F_i(x)=\sum_{i=0}^W\frac{(-1)^{i}}{i!}\sum_{n\ge
i-1}\frac{n+1}{(n+1-i)!}u^n\)
令 \(n'=n+1-i\) , \(n=n'+i-1\) ,将 \(n'\) 带入
\(\displaystyle
F_i(x)=\sum_{i=0}^W\frac{(-1)^{i}}{i!}\sum_{n\ge
0}\frac{n+i}{n!}u^{n+i-1}\)
将 \(n,i\) 拆开
\(\displaystyle F_i(x)=\sum_{i=0}^W
\frac{(-1)^{i}}{i!}(u^{i}\sum_{n\ge
0}\frac{1}{n!}u^{n}+u^{i-1}\sum_{n\ge 0}\frac{i}{n!}u^{n})\)
\(\displaystyle F_i(x)=\sum_{i=0}^W
\frac{(-1)^{i}}{i!}(u^{i}+iu^{i-1})e^u\)
容易发现我们需要多项式是 \(F(x)=e^x-\prod
F_i(x)\)
最终 \(F(x)\) 的每一项,都会是 \(x^k e^{cx}\) 的形式
其中 \(e^u\) 中的 \(u\) 总是 \(\frac{1}{S}(L-iK)x\) ,合并之后 \(L\) 之和总是存在,记录 \(\sum i\) 即可,为 \(O(S)\)
而每项要么是 \(u^ie^u\) 要么是 \(u^{i-1}e^u\) ,可以考虑记录一下 \(u^{i-1}e^u\) 出现的次数,为 \(O(n)\)
我们的多项式项数是 \(O(nS)\) 的
\[ \ \]
最终我们还需要对于每一项计算答案
我们要计算 \(\displaystyle \sum_{n\ge
0}n![x^n]F(x)\) ,考虑形如 \(x^ke^{cx}\) 一项的贡献
\(\displaystyle \sum_{n\ge k}n=\sum_{n\ge k}\frac{n!}{(n-k)!}c^{n-k}=k!\sum_{n\ge
0}\binom{n+k}{n}c^{n}\)
由于 \(\displaystyle
\binom{n+k}{n}=(-1)^{n}\binom{-k-1}{n}\)
带入广义二项式定理得到
\(\displaystyle k!\sum_{n\ge
0}\binom{n+k}{n}c^{n}=k!(1-c)^{-k-1}\)
根据是否用 \(\text{NTT}\)
优化,复杂度会有所不同
over.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 #include <bits/stdc++.h> using namespace std;typedef double db;typedef long double ldb;typedef long long ll;typedef unsigned long long ull;#define reg register #define pb push_back #define mp make_pair #define Mod1(x) ((x>=P)&&(x-=P)) #define Mod2(x) ((x<0)&&(x+=P)) #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i) #define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i) template <class T > inline void cmin (T &a,const T &b) { ((a>b)&&(a=b)); }template <class T > inline void cmax (T &a,const T &b) { ((a<b)&&(a=b)); }char IO;template <class T =int > T rd (){ T s=0 ; int f=0 ; while (!isdigit (IO=getchar ())) if (IO=='-' ) f=1 ; do s=(s<<1 )+(s<<3 )+(IO^'0' ); while (isdigit (IO=getchar ())); return f?-s:s; } const int N=1 <<11 |10 ,P=998244353 ;int n,m,k;ll qpow (ll x,ll k=P-2 ) { ll res=1 ; for (;k;k>>=1 ,x=x*x%P) if (k&1 ) res=res*x%P; return res; } int rev[N],I[N],J[N];typedef vector <int > V;void Init () { rep (i,J[0 ]=1 ,N-1 ) J[i]=1ll *J[i-1 ]*i%P; I[N-1 ]=qpow (J[N-1 ]); drep (i,N-1 ,1 ) I[i-1 ]=1ll *I[i]*i%P; } int Init (int n) { int R=1 ,c=-1 ; while (R<=n) R<<=1 ,c++; rep (i,0 ,R-1 ) rev[i]=(rev[i>>1 ]>>1 )|((i&1 )<<c); return R; } void NTT (int n,V &a,int f) { static int e[N>>1 ]; rep (i,0 ,n-1 ) if (i<rev[i]) swap (a[i],a[rev[i]]); for (int i=e[0 ]=1 ;i<n;i<<=1 ) { ll t=qpow (f==1 ?3 :(P+1 )/3 ,(P-1 )/i/2 ); for (int j=i-2 ;j>=0 ;j-=2 ) e[j+1 ]=(e[j]=e[j>>1 ])*t%P; for (int l=0 ;l<n;l+=i*2 ) { for (int j=l;j<l+i;++j) { int t=1ll *e[j-l]*a[j+i]%P; a[j+i]=a[j]-t,Mod2 (a[j+i]); a[j]+=t,Mod1 (a[j]); } } } if (f==-1 ) { ll Inv=1ll *I[n]*J[n-1 ]%P; rep (i,0 ,n-1 ) a[i]=a[i]*Inv%P; } } V operator * (V a,V b){ if (!a.size () || !b.size ()) return {}; int n=a.size ()+b.size ()-1 ,R=Init (n); a.resize (R),b.resize (R); NTT (R,a,1 ),NTT (R,b,1 ); rep (i,0 ,R-1 ) a[i]=1ll *a[i]*b[i]%P; NTT (R,a,-1 ); a.resize (n); return a; } V operator + (V a,V b){ if (a.size ()<b.size ()) swap (a,b); rep (i,0 ,b.size ()-1 ) a[i]+=b[i],Mod1 (a[i]); return a; } V F[55 ],A,B; int S,L[55 ];int main () { Init (); n=rd (),k=rd (); rep (i,1 ,n) S+=L[i]=rd (); sort (L+1 ,L+n+1 ); int InvS=qpow (S); F[0 ]={1 }; rep (i,1 ,n) { int W=(L[i]-1 )/k; A.clear (),A.resize (W+1 ); B.clear (),B.resize (W+1 ); rep (j,0 ,W) { int w=1ll *(L[i]-j*k)*InvS%P; A[j]=1ll *(j&1 ?P-I[j]:I[j])*qpow (w,j)%P; if (j) B[j]=1ll *(j&1 ?P-I[j]:I[j])*qpow (w,j-1 )%P*j%P; } drep (j,i,0 ) { if (!j) F[j]=F[j]*A; else F[j]=F[j]*A+F[j-1 ]*B; } } int ans=0 ; rep (i,0 ,n) { rep (j,max (i,1 ),F[i].size ()-1 ) if (F[i][j]) { int k=j-i; ans=(ans+1ll *F[i][j]*J[k]%P*qpow (1ll *j*::k*InvS%P,P-1 -k-1 ))%P; } } ans=(P-ans)%P; printf ("%d\n" ,ans); }