zoukankan      html  css  js  c++  java
  • BZOJ 3684 大朋友和多叉树

    BZOJ 3684 大朋友和多叉树

    Description

    我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树。对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的:点权为1的结点是叶子结点;对于任一点权大于1的结点u,u的孩子数目deg[u]属于集合D,且u的点权等于这些孩子结点的点权之和。
    给出一个整数s,你能求出根节点权值为s的神犇多叉树的个数吗?请参照样例以更好的理解什么样的两棵多叉树会被视为不同的。
    我们只需要知道答案关于(950009857)(453*2^{21}+1),一个质数)取模后的值。

    Input

    第一行有(2)个整数(s,m)
    第二行有(m)个互异的整数,(d[1],d[2],…,d[m]),为集合(D)中的元素。

    Output

    输出一行仅一个整数,表示答案模(950009857)的值。

    Sample Input

    4 2

    2 3

    Sample Output

    10


    前置知识

    ( ext{Lagrange})反演(金策的论文中有讲):

    若两个没有常数项的函数(f(x))(g(x))满足:

    [f(g(x))=x ]

    (也称这两个函数互为复合逆。)

    我们就有:

    [[x^n]g(x)=frac{1}{n}[w^{n-1}](frac{w}{f(w)})^n ]


    (T(x))为答案的生成函数。

    我们有:

    [T(x)=x+sum_{iin D}{T(x)}^i ]

    加上一个(x)是因为要考虑(x)为叶子的情况。

    移项:

    [T(x)-sum_{iin D}{T(x)}^i=x ]

    设:

    [f(x)=x-sum_{iin D}x^i ]

    则:

    [f(T(x))=x\ Rightarrow [x^n]T(x)=frac{1}{n}[w^{n-1}](frac{w}{f(w)})^n ]

    (frac{w}{f(w)})上下约掉(w)后发现相当于将(f(w))的每一项向左平移再求逆。

    然后:

    [f(x)^k=exp(kln(f(x))) ]

    代码:

    #include<bits/stdc++.h>
    #define ll long long
    #define N 100005
    
    using namespace std;
    inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}
    
    const ll mod=950009857;
    ll ksm(ll t,ll x) {
    	ll ans=1;
    	for(;x;x>>=1,t=t*t%mod)
    		if(x&1) ans=ans*t%mod;
    	return ans;
    }
    
    ll NTT(ll *a,int d,int flag) {
    	static int rev[N<<2];
    	static int G=7;
    	int n=1<<d;
    	for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<d-1);
    	for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
    	for(int s=1;s<=d;s++) {
    		int len=1<<s,mid=len>>1;
    		ll w=flag==1?ksm(G,(mod-1)/len):ksm(G,mod-1-(mod-1)/len);
    		for(int i=0;i<n;i+=len) {
    			ll t=1;
    			for(int j=0;j<mid;j++,t=t*w%mod) {
    				ll u=a[i+j],v=a[i+j+mid]*t%mod;
    				a[i+j]=(u+v)%mod;
    				a[i+j+mid]=(u-v+mod)%mod;
    			}
    		}
    	}
    	if(flag==-1) {
    		ll inv=ksm(n,mod-2);
    		for(int i=0;i<n;i++) a[i]=a[i]*inv%mod;
    	}
    }
    
    void Inv(ll *inv,ll *a,int d) {
    	static ll A[N<<2];
    	if(!d) {
    		inv[0]=ksm(a[0],mod-2);
    		return ;
    	}
    	Inv(inv,a,d-1);
    	for(int i=0;i<1<<d;i++) A[i]=a[i];
    	for(int i=1<<d;i<1<<d+1;i++) A[i]=inv[i]=0;
    	NTT(A,d+1,1),NTT(inv,d+1,1);
    	for(int i=0;i<1<<d+1;i++) inv[i]=(2*inv[i]-inv[i]*inv[i]%mod*A[i]%mod+mod)%mod;
    	NTT(inv,d+1,-1);
    	for(int i=1<<d;i<1<<d+1;i++) inv[i]=0;
    }
    
    void Der(ll *ans,ll *a,int d) {
    	int n=1<<d;
    	for(int i=0;i<n-1;i++) ans[i]=a[i+1]*(i+1)%mod;
    	ans[n-1]=0;
    }
    
    void Int(ll *ans,ll *a,int d) {
    	int n=1<<d;
    	for(int i=n-1;i;i--) ans[i]=a[i-1]*ksm(i,mod-2)%mod;
    	ans[0]=0;
    }
    
    void Ln(ll *ln,ll *a,int d) {
    	static ll inv[N<<2],der[N<<2];
    	for(int i=0;i<1<<d+1;i++) inv[i]=der[i]=0;
    	Inv(inv,a,d);Der(der,a,d);
    	NTT(inv,d+1,1),NTT(der,d+1,1);
    	for(int i=0;i<1<<d+1;i++) ln[i]=inv[i]*der[i]%mod;
    	NTT(ln,d+1,-1);
    	Int(ln,ln,d);
    	for(int i=1<<d;i<1<<d+1;i++) ln[i]=0;
    }
    
    void Exp(ll *ex,ll *a,int d) {
    	static ll A[N<<2],ln[N<<2];
    	if(d==0) {
    		ex[0]=1;
    		return ;
    	}
    	Exp(ex,a,d-1);
    	for(int i=0;i<1<<d+1;i++) A[i]=ln[i]=0;
    	for(int i=0;i<1<<d;i++) A[i]=a[i];
    	Ln(ln,ex,d);
    	NTT(ln,d+1,1),NTT(A,d+1,1);
    	NTT(ex,d+1,1);
    	for(int i=0;i<1<<d+1;i++) ex[i]=ex[i]*(1-ln[i]+A[i]+mod)%mod;
    	NTT(ex,d+1,-1);
    	for(int i=1<<d;i<1<<d+1;i++) ex[i]=0;
    }
    
    ll A[N<<2],inv[N<<2],ln[N<<2],ex[N<<2];
    ll f[N<<2];
    int n,m;
    
    int main() {
    	n=Get(),m=Get();
    	int d=ceil(log2(n+1));
    	for(int i=1;i<=m;i++) {
    		int a=Get();
    		f[a-1]=mod-1;
    	}
    	f[0]=1;
    	Inv(inv,f,d);
    	Ln(ln,inv,d);
    	for(int i=0;i<1<<d;i++) ln[i]=ln[i]*n%mod;
    	Exp(ex,ln,d);
    	cout<<ex[n-1]*ksm(n,mod-2)%mod;
    	return 0;
    }
    
  • 相关阅读:
    模拟伪造浏览器并获取json数据:
    Inno Setup命令行安装卸载参数
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——EmpDao层代码
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——hibernate的config文件(hibernate.cfg.xml)
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——hibernate的config文件(hibernate.cfg.xml)
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Dept实体类和对应的配置信息
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Dept实体类和对应的配置信息
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Emp实体类和对应的配置信息
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Emp实体类和对应的配置信息
    常用的字符串加密解密工具类
  • 原文地址:https://www.cnblogs.com/hchhch233/p/10720060.html
Copyright © 2011-2022 走看看