[cf1479E]School Clubs
对于当前班级状态$S$,定义一个函数$\varphi(S)$,要求其满足:
令结束状态为$S_{end}$,对于任意$S\ne S_{end}$,若其下一个状态为$S'$,则$E(\varphi(S)-\varphi(S'))=1$
由此,归纳即可得到$S$的期望结束步数为为$\varphi(S)-\varphi(S')$
对于一个状态$S$,注意到其与班级编号无关,因此不妨假设其第$i$个班级有$a_{i}$个人(共$m$个班级),再定义一个函数$g(x)$,令$\varphi(S)=\sum_{i=1}^{m}g(a_{i})$
由于为空的班级不影响状态,因此$g(0)=0$
更进一步的,根据$E(\varphi(S)-\varphi(S'))=1$,可得
$$
\frac{1}{2}\sum_{i=1}^{m}\frac{a_{i}}{n}(\Delta_{g}(a_{i}-1)-g(1))+\frac{1}{2}\sum_{i=1}^{m}\sum_{j=1}^{m}\frac{a_{i}a_{j}}{n^{2}}(\Delta_{g}(a_{i}-1)-\Delta_{g}(a_{j}-[i=j]))=1
$$
(其中$\Delta_{g}(x)=g(x+1)-g(x)$)
后者在$i=j$时为0,在$i\ne j$时将两个枚举拆开,即
$$
\frac{1}{2}\sum_{i=1}^{m}\frac{a_{i}}{n}(\Delta_{g}(a_{i}-1)-g(1))+\frac{1}{2}\sum_{i=1}^{n}\frac{a_{i}(n-a_{i})}{n^{2}}(\Delta_{g}(a_{i}-1)-\Delta_{g}(a_{i}))=1
$$
将其整理后,即
$$
\sum_{i=1}^{m}\frac{a_{i}}{2n}[(2-\frac{a_{i}}{n})\Delta_{g}(a_{i}-1)-(1-\frac{a_{i}}{n})\Delta_{g}(a_{i})-g(1)]=1
$$
当对于每一个$a_{i}$,中括号内的值恰为$2$时,根据$\sum_{i=1}^{m}a_{i}=n$,即成立
令$g(1)=-2$,再化简后即可得到$\Delta_{g}(x)$
$$
\Delta_{g}(x)=\frac{2n-x}{n-x}\Delta_{g}(x-1)=\prod_{i=1}^{x}\frac{2n-i}{n-i}\Delta_{g}(0)
$$
根据$g(0)=0$以及$g(1)=-2$,可得初始状态$\Delta_{g}(0)=-2$
由此,可得$g(x)=g(0)+\sum_{i=0}^{x-1}\Delta_{g}(i)=-2\sum_{i=0}^{x-1}\prod_{j=1}^{i}\frac{2n-j}{n-j}$,问题即求$\sum_{i=1}^{m}g(a_{i})-g(n)$
之后暴力$o(n)$计算即可,为了避免每一次求逆,需要用分数的形式计算,以及使用”GNU G++17 9.2.0(64 bit,msys 2)“的编译器即可通过
标算做到了$o(\sqrt{n}\log n+m\sqrt{n})$的复杂度,可以看cf上的题解
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define M 1005 4 #define mod 998244353 5 #define ll long long 6 int n,m,x,ans,a[M]; 7 ll qpow(int n,int m){ 8 ll s=n,ans=1; 9 while (m){ 10 if (m&1)ans=ans*s%mod; 11 s=s*s%mod; 12 m>>=1; 13 } 14 return ans; 15 } 16 ll g(int x){ 17 ll s1=1,s2=1,ans1=0,ans2=1; 18 for(int i=1;i<=x;i++){ 19 ans1=(s1*ans2+s2*ans1)%mod; 20 ans2=s2*ans2%mod; 21 s1=s1*(2*n-i)%mod; 22 s2=s2*(n-i)%mod; 23 } 24 return (mod-2)*ans1%mod*qpow(ans2,mod-2)%mod; 25 } 26 int main(){ 27 scanf("%d",&m); 28 for(int i=1;i<=m;i++){ 29 scanf("%d",&a[i]); 30 n+=a[i]; 31 } 32 for(int i=1;i<=m;i++)ans=(ans+g(a[i]))%mod; 33 printf("%d",(ans+mod-g(n))%mod); 34 }