[luogu5564]Say Goodbye
两树相同的定义与题中相同,并定义两树完全相同当且仅当在不允许基环旋转的条件下相同
枚举基环的长度$l$,根据置换群的理论,答案即$\frac{1}{l}\sum_{i=1}^{l}f(i)$(其中$f(i)$表示满足"基环旋转$i$次后与原基环树完全相同"的不完全相同的树个数)
关于这个结论,考虑一棵树将基环旋转$1,2,...,l$次的$l$棵树(这$l$棵树相同),其中每一种不完全相同的树的贡献即其中与其完全相同的树个数,那么所有树总贡献即为$l$,因此除以$l$后即为答案
不难发现$f(i)$仅取决于$\gcd(l,i)$,不妨枚举后者,答案即$\frac{1}{l}\sum_{d\mid l}\varphi(\frac{l}{d})f(d)$
为了方便,我们枚举$\frac{l}{d}$,答案即$\frac{1}{l}\sum_{d\mid l}\varphi(d)f(\frac{l}{d})$
考虑$f(\frac{l}{d})$,即统计有多少组树$(T_{1},T_{2},...,T_{\frac{l}{d}})$(不允许为空),使得其点数和为$\frac{n}{d}$(若$d\not\mid n$即无解),两组树不同当且仅当满足$\exists 1\le i\le d,T_{i}$和$T'_{i}$不同
关于这个问题,显然形态和染色独立,分别考虑:
考虑$n$个点不同形态的树有多少棵,即长为$n-1$的括号序列数(注意首尾的两个括号为根,必须要匹配),也即$C_{n-1}$(其中$C_{n}$为卡特兰数第$n$项,有$C_{n}=\frac{{2n\choose n}}{n+1}$)
令$C(x)$为$C_{n-1}$的生成函数,即$C(x)=\sum_{n\ge 1}C_{n-1}x^{n}$,那么方案数即$[x^{\frac{n}{d}}]C^{\frac{l}{d}}(x)$
考虑染色数,若$\forall 1\le i\le m,d\mid a_{i}$则方案数为$\frac{\frac{n}{d}!}{\prod_{i=1}^{m}\frac{a_{i}}{d}!}$,否则为0
综上,最终答案即
$$
\sum_{l=2}^{n}\frac{1}{l}\sum_{d\mid \gcd(l,g)}\varphi(d)\cdot [x^{\frac{n}{d}}]C^{\frac{l}{d}}(x)\cdot\frac{\frac{n}{d}!}{\prod_{i=1}^{m}\frac{a_{i}}{d}!}
$$
(其中$g=\gcd(a_{1},a_{2},...,a_{m})$,显然此时$g\mid n$)
交换枚举顺序,即
$$
\left(\sum_{d\mid g}\frac{\varphi(d)}{d}\cdot \frac{\frac{n}{d}!}{\prod_{i=1}^{m}\frac{a_{i}}{d}!}\sum_{l=1}^{\frac{n}{d}}\frac{[x^{\frac{n}{d}}]C^{l}(x)}{l} \right)-C_{n-1} \frac{n!}{\prod_{i=1}^{m}a_{i}!}
$$
(注意要减去$l=1$的情况)
对于这些式子,除了$\sum_{l=1}^{\lfloor\frac{n}{d}\rfloor}\frac{[x^{\frac{n}{d}}]C^{l}(x)}{l}$都可以快速计算($\frac{\frac{n}{d}!}{\prod_{i=1}^{m}\frac{a_{i}}{d}!}$暴力即可,复杂度为$o(\sigma(g)m)$)
对于$\sum_{l=1}^{\lfloor\frac{n}{d}\rfloor}\frac{[x^{\frac{n}{d}}]C^{l}(x)}{l}$,注意到都是$[x^{\frac{n}{d}}]$,不妨先将多项式求和,即求$[x^{\frac{n}{d}}]\sum_{l=1}^{\frac{n}{d}}\frac{C^{l}(x)}{l}$
关于后者,由于$C(x)$的最低次为1,因此不妨删去$l$的上限,即求$[x^{\frac{n}{d}}]\sum_{l\ge 1}\frac{C^{l}}{l}$
关于右半部分,也即$-\ln (1-C)$,证明考虑$f(x)=\ln x$在1处的泰勒展开,即
$$
f(x)=\sum_{i\ge 0}\frac{(x-1)^{i}f^{(i)}(1)}{i!}=-\sum_{i\ge 1}\frac{(x-1)^{i}\frac{(i-1)!}{(-1)^{i}}}{i!}=-\sum_{i\ge 1}\frac{(1-x)^{i}}{i}
$$
(其中$f^{(i)}(x)$指$f$的$i$阶导数,计算并归纳可以发现其为$-\frac{(i-1)!}{(-x)^{i}}$)
不难得到$-\ln(1-C)=\sum_{i\ge 1}\frac{C^{i}(x)}{i}$,即得证
由此,多项式求对数即可,时间复杂度为$o(\sigma(g)m+n\log n)$,可以通过
事实上,令$C_{0}(x)=\frac{C(x)}{x}=\sum_{n\ge 0}C_{n}x^{n}$,那么有通项公式
$$
[x^{n}]C_{0}^{m}(x)={2n+m-1\choose n}-{2n+m-1\choose n-1}
$$
关于这个式子的解释——
$[x^{n}]C_{0}^{m}(x)$实际上可以看作从$(0,0)$走到$(2n,0)$,要求每一步从$(x,y)$到$(x+1,y\pm 1)$,求所有与$y=-1$不交的路径贡献和,其中一条路径的贡献为${tot\choose m-1}$($tot$为该路径除起点和终点外与$x$轴的交点数)
事实上,这也等价于从$(0,0)$走到$(2n+m-1,1-m)$且与$y=-m$不交的路径数
关于两者的对应关系:
考虑前者路径,不断将其路径上与$y=0,-1,...,2-m$的某一个交点之后新增一步到$(x+1,y-1)$,即得到一条后者的路径,并且显然选择方式恰有${tot\choose m-1}$种
考虑后者的路径,分别将其路径上与$y=-1,-2,...,1-m$的第一次交点取出,显然这些交点的上一个步都是从$(x-1,y+1)$到$(x,y)$,删去这些步,即得到前者的路径
后者的路径数是一个经典的问题,在没有"与$y=-m$不交"的条件下,方案数显然为${2n+m-1\choose n-m}$,接下来考虑减去"与$y=-m$有交"的路径数,而这也等价于从$(0,-2m)$走到$(2n+m-1,1-m)$的路径数
关于两者的对应关系:显然两者的路径都与$y=-m$有交,那么将两者路径上第一次与$y=-m$相交之前的部分以$y=-m$为对称轴翻折,即可得到另一者的路径
后者的路径数显然为${2n+m-1\choose n-m-1}$(注意少向下一步还会多向上一步),即得证
类似地,可以得到
$$
[x^{n}]C^{m}(x)=[x^{n-m}]C_{0}^{m}(x)={2n-m-1\choose n-m}-{2n-m-1\choose n-m-1}
$$
由此,回到"交换枚举顺序"后的式子,直接使用通项公式计算即可
时间复杂度同样为$o(\sigma(g)m+n\log n)$,可以通过
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define mod 998244353 5 #define ll long long 6 int n,m,g,ans,a[N],fac[N<<1],inv[N<<1],Inv[N<<1],p[N],vis[N],phi[N]; 7 int gcd(int x,int y){ 8 if (!y)return x; 9 return gcd(y,x%y); 10 } 11 int c(int n,int m){ 12 if ((m<0)||(m>n))return 0; 13 return (ll)fac[n]*Inv[m]%mod*Inv[n-m]%mod; 14 } 15 int C(int n,int m){ 16 return (c(2*n-m-1,n-m)-c(2*n-m-1,n-m-1)+mod)%mod; 17 } 18 int C(int n){ 19 return (ll)c((n<<1),n)*inv[n+1]%mod; 20 } 21 int main(){ 22 fac[0]=inv[0]=inv[1]=Inv[0]=1; 23 for(int i=1;i<(N<<1);i++)fac[i]=(ll)fac[i-1]*i%mod; 24 for(int i=2;i<(N<<1);i++)inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; 25 for(int i=1;i<(N<<1);i++)Inv[i]=(ll)Inv[i-1]*inv[i]%mod; 26 phi[1]=1; 27 for(int i=2;i<N;i++){ 28 if (!vis[i]){ 29 p[++p[0]]=i; 30 phi[i]=i-1; 31 } 32 for(int j=1;(j<=p[0])&&(i*p[j]<N);j++){ 33 vis[i*p[j]]=1; 34 if (i%p[j])phi[i*p[j]]=phi[i]*phi[p[j]]; 35 else{ 36 phi[i*p[j]]=phi[i]*p[j]; 37 break; 38 } 39 } 40 } 41 scanf("%d%d",&n,&m); 42 g=n,ans=mod-(ll)C(n-1)*fac[n]%mod; 43 for(int i=1;i<=m;i++){ 44 scanf("%d",&a[i]); 45 g=gcd(g,a[i]); 46 ans=(ll)ans*Inv[a[i]]%mod; 47 } 48 for(int i=1;i<=g;i++) 49 if (g%i==0){ 50 int s=0; 51 for(int j=1;j<=n/i;j++)s=(s+(ll)C(n/i,j)*inv[j])%mod; 52 s=(ll)s*fac[n/i]%mod; 53 for(int j=1;j<=m;j++)s=(ll)s*Inv[a[j]/i]%mod; 54 ans=(ans+(ll)s*phi[i]%mod*inv[i])%mod; 55 } 56 printf("%d",ans); 57 }