传送门
题意:给定nnn和集合SSS,求含nnn个叶子结点、非叶子节点的儿子数在SSS内的树的个数 模 950009857(453×221+1)950009857(453\times2^{21}+1)950009857(453×221+1)。结点无标号但儿子间有顺序。
n≤105n \leq 10^5n≤105
算是拉格朗日反演模版题了吧……
先是拉格朗日反演
对于两个不含常数项,且一次项非000的多项式F(x),G(x)F(x),G(x)F(x),G(x),如果F(G(x))=xF(G(x))=xF(G(x))=x(当然要取模),称FFF是GGG的复合逆。
人话:反函数
根据高中数学知识,F(x)F(x)F(x)和G(x)G(x)G(x)互为反函数,所以G(F(x))=xG(F(x))=xG(F(x))=x也成立
所以下面的FFF和GGG可以互换
现在考虑G(F(x))=xG(F(x))=xG(F(x))=x,如果知道G(x)G(x)G(x)如何求F(x)F(x)F(x)的nnn次项系数
设
G(x)=∑i=1∞aixiG(x)=\sum_{i=1}^\infin a_ix^iG(x)=i=1∑∞aixi
代入F(x)F(x)F(x)
∑i=0∞aiFi(x)=x\sum_{i=0}^\infin a_iF^i(x)=xi=0∑∞aiFi(x)=x
闲着没事求个导
∑i=0∞iaiFi−1(x)F′(x)=1\sum_{i=0}^\infin ia_iF^{i-1}(x)F'(x)=1i=0∑∞iaiFi−1(x)F′(x)=1
同时除以Fn(x)F^n(x)Fn(x)
∑i=0∞iaiFi−n−1(x)F′(x)=1Fn(x)\sum_{i=0}^\infin ia_iF^{i-n-1}(x)F'(x)={1\over F^n(x)}i=0∑∞iaiFi−n−1(x)F′(x)=Fn(x)1
同时取−1-1−1次项
[x−1]∑i=0∞iaiFi−n−1(x)F′(x)=[x−1]1Fn(x)[x^{-1}]\sum_{i=0}^\infin ia_iF^{i-n-1}(x)F'(x)=[x^{-1}]{1\over F^n(x)}[x−1]i=0∑∞iaiFi−n−1(x)F′(x)=[x−1]Fn(x)1
什么?为什么有负数项?
这个涉及到一些抽象代数的知识,这里肯定讲不了了
不过可以简单粗暴的理解成:
两个多项式相除F(x)/G(x)F(x)/G(x)F(x)/G(x),发现G(x)G(x)G(x)没有常数项无法求逆,于是把G(x)G(x)G(x)写成G0(x)xnG_0(x)x^nG0(x)xn,其中G0(x)G_0(x)G0(x)有常数项。
这样G0(x)G_0(x)G0(x)就有逆了,算出来之后平移nnn位就有了负下标,形如
...a−2x−2+a−1x−1+a0+a1x+......a_{-2}x^{-2}+a_{-1}x^{-1}+a_0+a_1x+......a−2x−2+a−1x−1+a0+a1x+...
只需要知道:这个负下标是为了解决没有逆的情况,和多项式求逆不矛盾
好继续
[x−1]∑i=0∞iaiFi−n−1(x)F′(x)=[x−1]1Fn(x)[x^{-1}]\sum_{i=0}^\infin ia_iF^{i-n-1}(x)F'(x)=[x^{-1}]{1\over F^n(x)}[x−1]i=0∑∞iaiFi−n−1(x)F′(x)=[x−1]Fn(x)1
中间那团看着不爽,提出来研究一下
Fi−n−1(x)F′(x)F^{i-n-1}(x)F'(x)Fi−n−1(x)F′(x)
它等于
(Fi−n)′(x)i−n(F^{i-n})'(x)\over i-ni−n(Fi−n)′(x)
当i=ni=ni=n的时候没有意义,考虑i≠ni\neq ni=n
发现这个情况下Fi−nF^{i-n}Fi−n是个多项式……
什么?为什么?
首先i>ni>ni>n肯定没问题
i<ni<ni<n的时候相当于求个逆再求幂,它就(yi)算(ding)没有逆,我们也有负下标可以用来平移
这样允许负次幂的多项式求导之后一定没有−1-1−1次项,因为求导相当于集体左移一位,而000次项并不能移到−1-1−1次项……
(并不知道对不对,感性理解好了)
所以我们只需要考虑i=ni=ni=n的情况
也就是
F−1(x)F′(x)F^{-1}(x)F'(x)F−1(x)F′(x)
设
F(x)=∑i=1∞bixiF(x)=\sum_{i=1}^\infin b_ix^iF(x)=i=1∑∞bixi
那么上面的式子可以写成
b1+2b2x+3b3x2+4b4x3+...b1x+b2x2+b3x3+b4x4+...b_1+2b_2x+3b_3x^2+4b_4x^3+...\over b_1x+b_2x^2+b_3x^3+b_4x^4+...b1x+b2x2+b3x3+b4x4+...b1+2b2x+3b3x2+4b4x3+...
把下面强行拆开
b1+2b2x+3b3x2+4b4x3+...b1x11+b2b1x+b3b1x2+b4b1x3+...{b_1+2b_2x+3b_3x^2+4b_4x^3+...\over b_1x}{1\over 1+\frac{b_2}{b_1}x+{b_3\over b_1}x^2+{b_4 \over b_1}x^3+...}b1xb1+2b2x+3b3x2+4b4x3+...1+b1b2x+b1b3x2+b1b4x3+...1
注意到右边是一个正宗的多项式,并且常数项为111,存在逆元;而左边的b1b1xb_1\over b_1xb1xb1会贡献出一个x−1x^{-1}x−1
所以这一团的−1-1−1次项为111
代回原式
nan=[x−1]1Fn(x)na_n=[x^{-1}]\frac{1}{F^n(x)}nan=[x−1]Fn(x)1
[xn]G(x)=1n[x−1]1Fn(x)[x^n]G(x)=\frac{1}{n}[x^{-1}]\frac{1}{F^n(x)}[xn]G(x)=n1[x−1]Fn(x)1
没了……
哎等等,道理我都懂,可是负次幂怎么求呢?
那就右边平移吧
[xn]G(x)=1n[xn−1][xF(x)]n[x^n]G(x)=\frac{1}{n}[x^{n-1}][\frac{x}{F(x)}]^n[xn]G(x)=n1[xn−1][F(x)x]n
这样F(x)F(x)F(x)刚好可以约一个xxx,就可以求逆啦
然后这道题就很容易了
设f(n)f(n)f(n)表示nnn个叶子时的答案,有f(1)=1f(1)=1f(1)=1
然后构造生成函数F(x)F(x)F(x)
可以得到
F(x)=∑d∈SFd(x)+xF(x)=\sum_{d\in S}F^d(x)+xF(x)=d∈S∑Fd(x)+x
移个项
F(x)−∑d∈SFd(x)=xF(x)-\sum_{d\in S}F^d(x)=xF(x)−d∈S∑Fd(x)=x
设
G(x)=x−∑d∈SxdG(x)=x-\sum_{d\in S}x^dG(x)=x−d∈S∑xd
有
G(F(x))=xG(F(x))=xG(F(x))=x
套结论即可
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#define MAXN 400005
using namespace std;
inline int read()
{int ans=0;char c=getchar();while (!isdigit(c)) c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return ans;
}
const int MOD=950009857;
typedef long long ll;
inline int add(const int& x,const int& y){return x+y>=MOD? x+y-MOD:x+y;}
inline int dec(const int& x,const int& y){return x<y? x-y+MOD:x-y;}
inline int qpow(int a,int p)
{int ans=1;while (p){if (p&1) ans=(ll)ans*a%MOD;a=(ll)a*a%MOD;p>>=1;}return ans;
}
#define inv(x) qpow(x,MOD-2)
int rt[2][22];
int l,r[MAXN];
inline void init(){for (int i=0;i<(1<<l);i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));}
inline void NTT(int* a,int type)
{int lim=1<<l;for (int i=0;i<lim;i++) if (i<r[i]) swap(a[i],a[r[i]]);for (int L=0;L<l;L++){int mid=1<<L,len=mid<<1,Wn=rt[type][L+1];for (int s=0;s<lim;s+=len)for (int k=0,w=1;k<mid;k++,w=(ll)w*Wn%MOD){int x=a[s+k],y=(ll)a[s+mid+k]*w%MOD;a[s+k]=add(x,y),a[s+mid+k]=dec(x,y);}}if (type){int t=inv(lim);for (int i=0;i<lim;i++) a[i]=(ll)a[i]*t%MOD;}
}
void getinv(int* A,int* B,int n)
{static int f[MAXN],t[MAXN];if (n==1) return (void)(*B=inv(*A));getinv(A,t,(n+1)>>1);l=0;while ((1<<l)<(n<<1)) ++l;init();for (int i=0;i<n;i++) f[i]=A[i];for (int i=n;i<(1<<l);i++) f[i]=t[i]=0;NTT(f,0);NTT(t,0);for (int i=0;i<(1<<l);i++) B[i]=(ll)t[i]*dec(2,(ll)f[i]*t[i]%MOD)%MOD;NTT(B,1);for (int i=n;i<(1<<l);i++) B[i]=0;
}
inline void deriv(int* A,int* B,int n){for (int i=0;i<n-1;i++) B[i]=(ll)A[i+1]*(i+1)%MOD;B[n-1]=0;}
inline void integ(int* A,int* B,int n){for (int i=1;i<n;i++) B[i]=(ll)A[i-1]*inv(i)%MOD;B[0]=0;}
void getln(int* A,int* B,int n)
{static int f[MAXN],g[MAXN];deriv(A,f,n);getinv(A,g,n);for (int i=n;i<(1<<l);i++) f[i]=g[i]=0;NTT(f,0);NTT(g,0);for (int i=0;i<(1<<l);i++) f[i]=(ll)f[i]*g[i]%MOD;NTT(f,1);integ(f,B,n);for (int i=n;i<(1<<l);i++) B[i]=0;
}
void getexp(int* A,int* B,int n)
{static int f[MAXN],g[MAXN];if (n==1) return (void)(*B=1);getexp(A,g,(n+1)>>1);getln(g,f,n);for (int i=0;i<n;i++) f[i]=dec(A[i],f[i]);++f[0];for (int i=n;i<(1<<l);i++) f[i]=g[i]=0;NTT(f,0);NTT(g,0);for (int i=0;i<(1<<l);i++) B[i]=(ll)f[i]*g[i]%MOD;NTT(B,1);for (int i=n;i<(1<<l);i++) B[i]=0;
}
int a[MAXN],t[MAXN];
int main()
{rt[0][21]=qpow(5,453);rt[1][21]=inv(rt[0][21]);for (int i=20;i>=0;i--){rt[0][i]=(ll)rt[0][i+1]*rt[0][i+1]%MOD;rt[1][i]=(ll)rt[1][i+1]*rt[1][i+1]%MOD;}int n,k;n=read(),k=read();a[0]=1;while (k--) a[read()-1]=MOD-1;getinv(a,t,n);getln(t,a,n);for (int i=0;i<n;i++) a[i]=(ll)a[i]*n%MOD;getexp(a,t,n);int ans=(ll)t[n-1]*inv(n)%MOD;printf("%d\n",ans);return 0;
}