zoukankan      html  css  js  c++  java
  • 题解 大朋友和多叉树

    题目传送门

    题目大意

    给出集合(S)和整数(n),求出有多少个多叉树使得每个节点的孩子个数都在(S)中,且叶子个数为(n)

    思路

    啊,居然没有看出来可以用拉格朗日反演,果然还是自己太菜了。。。

    我们设答案的生成函数为(F)(G)为集合(S)的生成函数,可以得到:

    [F=sum_{iin S} F^i+x ]

    应该很显然吧,这里就懒得解释了。

    我们发现这个式子可以化成:

    [F=G(F)+x ]

    我们如果设(C(x)=x-G(c)),那我们就可以得到:

    [C(F)=x ]

    我们就发现(C)(F)互为复合逆,于是使用拉格朗日反演可以得到:

    [[x^n]F(x)=frac{1}{n}[x^{n-1}](frac{x}{C(x)})^n ]

    [=frac{1}{n}[x^{n-1}]exp(nln frac{x}{C(x)}) ]

    于是,我们就可以做到(Theta(nlog n))解决这个问题了。

    ( ext {Code})

    #include <bits/stdc++.h>
    using namespace std;
    
    #define Int register int
    #define mod 950009857
    #define ll long long
    #define MAXN 400005
    #define Gi 7
    
    int quick_pow (int a,int b,int c){
    	int res = 1;for (;b;b >>= 1,a = 1ll * a * a % c) if (b & 1) res = 1ll * res * a % c;
    	return res;
    }
    
    int limit = 1,l,r[MAXN];
    
    void NTT (int *a,int type){
    	for (Int i = 0;i < limit;++ i) if (i < r[i]) swap (a[i],a[r[i]]);
    	for (Int mid = 1;mid < limit;mid <<= 1){
    		int Wn = quick_pow (Gi,(mod - 1) / (mid << 1),mod);
    		if (type == -1) Wn = quick_pow (Wn,mod - 2,mod);
    		for (Int R = mid << 1,j = 0;j < limit;j += R){
    			for (Int k = 0,w = 1;k < mid;++ k,w = 1ll * w * Wn % mod){
    				int x = a[j + k],y = 1ll * w * a[j + k + mid] % mod;
    				a[j + k] = (x + y) % mod,a[j + k + mid] = (x + mod - y) % mod;
    			}
    		}
    	} 
    	if (type == 1) return ;
    	int Inv = quick_pow (limit,mod - 2,mod);
    	for (Int i = 0;i < limit;++ i) a[i] = 1ll * a[i] * Inv % mod;
    }
    
    int c[MAXN];
    
    void Solve (int len,int *a,int *b)
    {
    	if (len == 1) return b[0] = quick_pow (a[0],mod - 2,mod),void ();
    	Solve ((len + 1) >> 1,a,b);
    	limit = 1,l = 0;
    	while (limit < len << 1) limit <<= 1,l ++;
    	for (Int i = 0;i < limit;++ i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
    	for (Int i = 0;i < len;++ i) c[i] = a[i];
    	for (Int i = len;i < limit;++ i) c[i] = 0;
    	NTT (c,1);NTT (b,1);
    	for (Int i = 0;i < limit;++ i) b[i] = 1ll * b[i] * (2 + mod - 1ll * c[i] * b[i] % mod) % mod;
    	NTT (b,-1);
    	for (Int i = len;i < limit;++ i) b[i] = 0;
    }
    
    void deravitive (int *a,int n){
    	for (Int i = 1;i <= n;++ i) a[i - 1] = 1ll * a[i] * i % mod;
    	a[n] = 0;
    }
    
    void inter (int *a,int n){
    	for (Int i = n;i >= 1;-- i) a[i] = 1ll * a[i - 1] * quick_pow (i,mod - 2,mod) % mod;
    	a[0] = 0;
    }
    
    int b[MAXN];
    
    void Ln (int *a,int n){
    	memset (b,0,sizeof (b));
    	Solve (n,a,b);deravitive (a,n);
    	while (limit < (n << 1)) limit <<= 1,l ++;
    	for (Int i = 0;i < limit;++ i) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
    	NTT (a,1),NTT (b,1);
    	for (Int i = 0;i < limit;++ i) a[i] = 1ll * a[i] * b[i] % mod;
    	NTT (a,-1),inter (a,n);
    	for (Int i = n + 1;i < limit;++ i) a[i] = 0;
    }
    
    int F0[MAXN];
    
    void Exp (int *a,int *B,int n){
    	if (n == 1) return B[0] = 1,void ();
    	Exp (a,B,(n + 1) >> 1);
    	for (Int i = 0;i < limit;++ i) F0[i] = B[i];
    	Ln (F0,n);
    	F0[0] = (a[0] + 1 + mod - F0[0]) % mod;
    	for (Int i = 1;i < n;++ i) F0[i] = (a[i] + mod - F0[i]) % mod;
    	NTT (F0,1);NTT (B,1);	
    	for (Int i = 0;i < limit;++ i) B[i] = 1ll * F0[i] * B[i] % mod;
    	NTT (B,-1);
    	for (Int i = n;i < limit;++ i) B[i] = 0;
    }
    
    template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
    template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
    template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
    
    int s,m,G[MAXN],G_[MAXN];
    
    signed main(){
    	read (s,m);
    	for (Int i = 1,x;i <= m;++ i) read (x),G[x - 1] = mod - 1;
    	G[0] = 1,Solve (s + 1,G,G_),memset (G,0,sizeof (G)),Ln (G_,s);
    	for (Int i = 0;i <= s;++ i) G_[i] = 1ll * G_[i] * s % mod;
    	Exp (G_,G,s + 1),write (1ll * G[s - 1] * quick_pow (s,mod - 2,mod) % mod),putchar ('
    ');
    	return 0;
    }
    
  • 相关阅读:
    Coursera课程《Python数据结构》中课件
    Coursera课程《Python数据结构》中课程目录
    Coursera课程《大家的编程》(Python入门)中课程目录
    Python for everyone chapter 1
    Coursera课程《大家的python》(Python for everyone)课件
    Coursera课程《大家的Python》中一些资料
    局部敏感哈希 Kernelized Locality-Sensitive Hashing Page
    CVPR14 图像检索papers
    Sequential projection learning for hashing阅读笔记
    Hashing图像检索源码及数据库总结
  • 原文地址:https://www.cnblogs.com/Dark-Romance/p/13289478.html
Copyright © 2011-2022 走看看