題目連接php
求知足以下條件的多叉樹個數: 1.每個點的兒子個數在給定的集合 $S$ 內 2.總的葉子節點樹爲 $s$c++
兒子之間有順序關係,但節點是沒有標號的。函數
拉格朗日反演板子題。spa
(彷佛不像是個反演)code
拉格朗日反演:get
用來求 複合逆。it
若是兩個多項式 $F(x),G(x)$ 知足常數項均爲 0,一次項均不爲 0,而且 $G(F(x))=x$,那麼稱 $F(x)$ 與 $G(x)$ 互爲複合逆(其實就是反函數)。 其中 $F(x)$ 和 $G(x)$ 能夠互換。class
結論以下:二叉樹
$$[x^n]F(x)=\frac{1}{n}[x^{-1}]\frac{1}{G^n(x)}$$static
證實工做及實際作法:
這個式子裏怎麼有 $x^{-1}$ 啊...聽說是抽象代數裏的,直接懵逼。
先無論這些,僞裝咱們容許下標爲負,先來隨便亂推一下這個式子。
$$G(F(x))=x$$
$$\sum_{i=1}a_iF^i(x)=x$$
這裏寫成了形式冪級數的形式。 咱們兩邊對 $x$ 求導。
$$\sum_{i=1}ia_iF^{i-1}(x)F'(x)=1$$
兩邊同時除掉 $F^n(x)$,取 $[x^{-1}]$(我也不知道我在幹什麼) $$[x^{-1}]\sum_{i=1}ia_iF^{i-n-1}(x)F'(x)=[x^{-1}]\frac{1}{F^n(x)}$$
當 $i\neq n$ 時,$F^{i-n-1}(x)F'(x)=\dfrac{\big(F^{i-n}(x)\big)'}{i-n}$
求導後 $x^{-1}$ 項係數必定是 0。 因此只考慮 $i=n$ 的狀況。
這時 $$F^{-1}(x)F'(x)=\dfrac{\sum_{i=1} ia_ix^{i-1}}{\sum_{i=1}a_ix^i}$$
$$F^{-1}(x)F'(x)=\dfrac{\sum_{i=1} ia_ix^{i-1}}{a_1x}·\dfrac{1}{1+\sum_{i=1}\frac{a_{i+1}}{a_1}x^i} $$
後面那個多項式可以求逆,它的逆的常數項顯然爲 1,所以不存在 $-1$ 次方項。 而前面那個多項式的 $[x^{-1}]$ 就是 : $\frac{a_1}{a_1}=1$ 因此 : $[x^{-1}] F^{-1}(x)F'(x)=1$
因此由以前的式子: $[x^{-1}]na_nF^{-1}(x)F'(x)=[x^{-1}]\frac{1}{F^n(x)}$
那麼就證完了: $$a_n=\frac{1}{n}[x^{-1}]\frac{1}{F^n(x)}$$
可是咱們並無辦法直接求解 $[x^{-1}]$,因此咱們能夠把下標移動一下。 $$a_n=\frac{1}{n}[x^{n-1}]\frac{x^n}{F^n(x)}$$ 這裏面乘了個 $x^n$,哪裏來的 $x^{n-1}$ 係數啊,而後$F(x)$尚未逆我怎麼求啊 $QAQ$
注意到 $F(x)$ 常數項爲 $0$,而一次項不爲 $0$
因而乎: $$a_n=\frac{1}{n}[x^{n-1}]\frac{1}{\big(\frac{F(x)}{x}\big)^n}$$ 這個好像就有 $x^{n-1}$了,並且還有逆,萬事大吉。
回到本題,按照小朋友和二叉樹的套路直接弄個生成函數。
設 $F(x)$ 是生成一棵含 $i$ 個葉子節點的合法的樹的這個數列的生成函數 。
生成方式顯然就是把一堆子樹組合起來。 $$F(x)=x+\sum_{i\in S}F^i(x)$$ 枚舉有幾個兒子,注意這裏咱們的下標表示的是葉子個數,因此後面的多項式不用乘上 $x$ 而且因爲一個節點是一個葉子,應該給 $x^1$ 方項係數加 $1$
移個項:
$$F(x)-\sum_{i\in S}F^i(x)=x$$
發現複合函數! 令 $G(x)=x-\sum_{i\in S}x^i$ 那麼: $$G(F(x))=x$$
咱們要求的是$F(x)$的第 $s$ 次方項係數而後就是套公式的事了。
什麼你說你不想寫 多項式快速冪 ?
注意到咱們是在 $bzoj$ 上進行評測,時間限制是總時間。 因此咱們直接寫倍增快速冪就能在 $bzoj$ 上經過此題(OWO)。
#include<bits/stdc++.h> #define Set(a,b) memset(a,b,sizeof(a)) #define Clear(a,_begin_,_end_) for(int i=_begin_;i<_end_;++i) a[i]=0 using namespace std; const int N=1e5+10,MAXN=N<<2; const int mod=950009857,phi=mod-1; template <typename T> inline void init(T&x){ x=0;char ch=getchar();bool t=0; for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=1; for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48); if(t) x=-x;return; } typedef long long ll; template<typename T>inline void Inc(T&x,int y){x+=y;if(x>=mod) x-=mod;return;} template<typename T>inline void Dec(T&x,int y){x-=y;if(x < 0) x+=mod;return;} template<typename T>inline int fpow(int x,T k){int ret=1;for(;k;k>>=1,x=(ll)x*x%mod) if(k&1) ret=(ll)ret*x%mod;return ret;} inline int Sum(int x,int y){x+=y;if(x>=mod) return x-mod;return x;} inline int Dif(int x,int y){x-=y;if(x < 0 ) return x+mod;return x;} int rader[MAXN],wn[30],iwn[30],Inv[MAXN]; inline void Calc(){ for(int i=0;i<30;++i) wn[i]=fpow(7,phi/(1<<i)),iwn[i]=fpow(wn[i],mod-2); Inv[1]=1;for(int i=2;i<MAXN;++i) Inv[i]=(ll)(mod-mod/i)*Inv[mod%i]%mod;return; } inline int Init(int n){int len=1,up=-1;while(len<=n)len<<=1,++up;for(int i=1;i<len;++i) rader[i]=(rader[i>>1]>>1)|((i&1)<<up);return len;} inline void NTT(int*A,int n,int f){ for(int i=1;i<n;++i) if(rader[i]>i) swap(A[i],A[rader[i]]); for(int i=1,h=1;i<n;++h,i<<=1){ int W= (~f) ? wn[h]:iwn[h]; for(int j=0,p=i<<1;j<n;j+=p) for(int w=1,k=0;k<i;++k,w=(ll)W*w%mod){ int X=A[j|k],Y=(ll)w*A[j|k|i]%mod; A[j|k]=Sum(X,Y),A[j|k|i]=Dif(X,Y); } }if(!~f) for(int i=0;i<n;++i) A[i]=(ll)A[i]*Inv[n]%mod; } int n,m; inline void Poly_Inv(int*F,int*I,int n){ if(n==1) {I[0]=1;return;} Poly_Inv(F,I,(n+1)>>1);int len=Init(n<<1); static int A[MAXN];for(int i=0;i<n;++i) A[i]=F[i];Clear(A,n,len); NTT(A,len,1);NTT(I,len,1); for(int i=0;i<len;++i) I[i]=Dif(2ll*I[i]%mod,(ll)I[i]*I[i]%mod*A[i]%mod); NTT(I,len,-1);Clear(I,n,len);return; } int main() { Calc();init(n),init(m); static int A[MAXN],G[MAXN];int x; for(int i=1;i<=m;++i) init(x),A[x-1]=phi;A[0]=1; int k=n;G[0]=1;int len=Init(n<<1); while(k) { NTT(A,len,1); if(k&1) { NTT(G,len,1); for(int i=0;i<len;++i) G[i]=(ll)G[i]*A[i]%mod; NTT(G,len,-1);Clear(G,n,len); } for(int i=0;i<len;++i) A[i]=(ll)A[i]*A[i]%mod; NTT(A,len,-1);Clear(A,n,len);k>>=1; } Set(A,0);Poly_Inv(G,A,n); int ans=(ll)A[n-1]*Inv[n]%mod; cout<<ans<<endl; return 0; }