【bzoj3684】 大朋友和多叉树 生成函数+多项式快速幂+拉格朗日反演

这题一看就觉得是生成函数的题...

我们不妨去推下此题的生成函数,设生成函数为$F(x)$,则$[x^s]F(x)$即为答案。

根据题意,我们得到 $F(x)=x+\sum_{i∈D} F^i(x)$,其中前面单独出现的$x$可以理解为空树的情况。

如果$i$的范围很小,那么我们就可以用求根公式去解多项式方程23333。

然而考虑到$i$最大为$10^5$,根据阿贝尔定理,无根式解,所以不能用此方法。

我们对原先的式子做一个移项,得$F(x)-\sum_{i∈D} F^i(x)=x$。

我们构造函数$G(x)=x-\sum_{i∈D}x^i$。

不难发现$G(F(x))=F(x)-\sum_{i∈D}F^i(x)=x$。也就是说$F(x)$和$G(x)$互为反函数。

然后我们现在已知$G(x)$,要求$F(x)$使得$G(F(x))=x$。也就是求$G(x)$的复合逆。

根据拉格朗日反演,若$G(F(x))=x$,则有$[x^s]F(x)=\dfrac{1}{s}[x^{-1}]\dfrac{1}{G^s(x)}$。

然后,我们对式子乘上$x^s$,得到$[x^s]F(x)=\dfrac{1}{s}[x^{s-1}](\dfrac{1}{G(x)})^s$。

然后后面就是多项式快速幂了。

 

  1 #include<bits/stdc++.h>
  2 #define G 7
  3 #define L long long
  4 #define MOD 950009857
  5 #define inv(x) pow_mod(x,MOD-2)
  6 #define M 1<<18
  7 using namespace std;
  8 
  9 L pow_mod(L x,L k){
 10     L ans=1;
 11     while(k){
 12         if(k&1) ans=ans*x%MOD;
 13         k=k>>1; x=x*x%MOD;
 14     }
 15     return ans;
 16 }
 17 
 18 void change(L a[],int n){
 19     for(int i=0,j=0;i<n-1;i++){
 20         if(i<j) swap(a[i],a[j]);
 21         int k=n>>1;
 22         while(j>=k) j-=k,k>>=1;
 23         j+=k;
 24     }
 25 }
 26 void NTT(L a[],int n,int on){
 27     change(a,n);
 28     for(int h=2;h<=n;h<<=1){
 29         L wn=pow_mod(G,(MOD-1)/h);
 30         for(int j=0;j<n;j+=h){
 31             L w=1;
 32             for(int k=j;k<j+(h>>1);k++){
 33                 L u=a[k],t=a[k+(h>>1)]*w%MOD;
 34                 a[k]=(u+t)%MOD;
 35                 a[k+(h>>1)]=(u-t+MOD)%MOD;
 36                 w=w*wn%MOD;
 37             }
 38         }
 39     }
 40     if(on==-1){
 41         L inv=inv(n);
 42         for(int i=0;i<n;i++) a[i]=a[i]*inv%MOD;
 43         reverse(a+1,a+n);
 44     }
 45 }
 46 
 47 void getinv(L a[],L b[],int n){
 48     if(n==1) return void(b[0]=inv(a[0]));
 49     static L A[M],B[M];
 50     memset(A,0,sizeof(A)); memset(B,0,sizeof(B));
 51     getinv(a,B,n>>1);
 52     for(int i=0;i<n;i++) A[i]=a[i];
 53     NTT(A,n<<1,1); NTT(B,n<<1,1);
 54     for(int i=0;i<(n<<1);i++) b[i]=(2*B[i]-A[i]*B[i]%MOD*B[i]%MOD+MOD)%MOD;
 55     NTT(b,n<<1,-1);
 56     for(int i=0;i<n;i++) b[n+i]=0;
 57 }
 58 
 59 void qiudao(L a[],L b[],int n){
 60     memset(b,0,sizeof(b));
 61     for(int i=1;i<n;i++) b[i-1]=i*a[i]%MOD;
 62 }
 63 void jifen(L a[],L b[],int n){
 64     memset(b,0,sizeof(b));
 65     for(int i=0;i<n;i++) b[i+1]=a[i]*pow_mod(i+1,MOD-2)%MOD;
 66 }
 67 
 68 void getln(L a[],L b[],int n){
 69     static L c[M],d[M];
 70     memset(c,0,M<<3); memset(d,0,M<<3);
 71     qiudao(a,c,n); getinv(a,d,n);
 72     NTT(c,n<<1,1); NTT(d,n<<1,1);
 73     for(int i=0;i<(n<<1);i++) c[i]=c[i]*d[i]%MOD;
 74     NTT(c,n<<1,-1);
 75     jifen(c,b,n);
 76 }
 77 
 78 void getexp(L a[],L b[],int n){
 79     if(n==1){b[0]=1; return;}
 80     static L lnb[M]; memset(lnb,0,M<<3);
 81     getexp(a,b,n>>1); getln(b,lnb,n);
 82     for(int i=0;i<n;i++) lnb[i]=(a[i]-lnb[i]+MOD)%MOD;
 83     lnb[n]=0;
 84     lnb[0]=(lnb[0]+1)%MOD;
 85     NTT(lnb,n<<1,1); NTT(b,n<<1,1);
 86     for(int i=0;i<(n<<1);i++) b[i]=b[i]*lnb[i]%MOD;
 87     NTT(b,n<<1,-1);
 88     for(int i=0;i<n;i++) b[i+n]=0;
 89 }
 90 
 91 L g[M]={0},f[M]={0};
 92 
 93 void pow_mod(L a[],L b[],int n,int k){
 94     memset(b,0,M<<3);
 95     getln(a,b,n);
 96     for(int i=0;i<n;i++) a[i]=b[i]*k%MOD;
 97     memset(b,0,M<<3);
 98     getexp(a,b,n);
 99 }
100 
101 int main(){
102     int n,m;
103     scanf("%d%d",&n,&m);
104     for(int i=1;i<=m;i++){
105         int x; scanf("%d",&x);
106         g[x-1]=-1;
107     }
108     g[0]=1;
109     int nn=1;while(nn<n) nn<<=1;
110     getinv(g,f,nn);
111     memset(g,0,sizeof(g)); 
112     pow_mod(f,g,nn,n);
113     L ans=inv(n)*g[n-1]%MOD;
114     cout<<ans<<endl;
115 }

 

posted @ 2018-05-27 21:22  AlphaInf  阅读(256)  评论(0编辑  收藏  举报