zoukankan      html  css  js  c++  java
  • [SCOI2003]严格N元树

    Description
    如果一棵树的所有非叶节点都恰好有 (n) 个儿子,那么我们称它为严格 (n) 元树。如果该树中最底层的节点深度为 (d)(根的深度为 (0)),那么我们称它为一棵深度为 (d) 的严格 (n) 元树。例如,深度为2的严格2元树有三个,如下图:

    image.png

    给出 (n,d),编程数出深度为 (d)(n) 元树数目。

    Input
    仅包含两个整数 (n,d(0<n leqslant 32,0 leqslant d leqslant 16))。输入数据保证你不需要考虑某一层多于 10241024 个节点的树(即 (nd leqslant 1024))。提示:答案保证不超过 200 位十进制数。

    Output
    仅包含一个数,即深度为 (d)(n) 元树的数目。

    Sample Input 1

    2 2
    

    Sample Output 1

    3
    

    Sample Input 2

    2 3
    

    Sample Output 2

    21
    

    Sample Input 3

    3 5
    

    Sample Output 3

    58871587162270592645034001
    

    我们首先考虑(n=2)的情况,记(F_x)表示深度为(x)的严格(n)元树个数,(S_x=sumlimits_{i=1}^xF_i),我们考虑(F_x)如何转移到(F_{x+1})

    考虑到深度增加,故我们新引入一个根节点,不难发现,(F_{x+1})的所有情况,其左右子树的深度均小于(x+1),故可得所有的情况数为(S_x^2)。显然,在这些情况中存在不合法的情况,因为要保证深度为(x+1),故子树至少有一个深度需要达到(x),用容斥原理可得(F_{x+1}=S_x^2-S_{x-1}^2)

    (n eq 2)呢?很显然这(n)个子节点是互相独立的,故可得(F_{x+1}=S_x^n-S_{x-1}^n)

    /*program from Wolfycz*/
    #include<map>
    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define Fi first
    #define Se second
    #define ll_inf 1e18
    #define MK make_pair
    #define sqr(x) ((x)*(x))
    #define pii pair<int,int>
    #define int_inf 0x7f7f7f7f
    using namespace std;
    typedef long long ll;
    typedef unsigned int ui;
    typedef unsigned long long ull;
    inline char gc(){
    	static char buf[1000000],*p1=buf,*p2=buf;
    	return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
    }
    template<typename T>inline T frd(T x){
    	int f=1; char ch=gc();
    	for (;ch<'0'||ch>'9';ch=gc())	if (ch=='-')    f=-1;
    	for (;ch>='0'&&ch<='9';ch=gc())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    template<typename T>inline T read(T x){
    	int f=1; char ch=getchar();
    	for (;ch<'0'||ch>'9';ch=getchar())	if (ch=='-')	f=-1;
    	for (;ch>='0'&&ch<='9';ch=getchar())	x=(x<<1)+(x<<3)+ch-'0';
    	return x*f;
    }
    inline void print(int x){
    	if (x<0)	putchar('-'),x=-x;
    	if (x>9)	print(x/10);
    	putchar(x%10+'0');
    }
    const int maxn=1e2;
    const int base=1e4;
    const int digit=4;
    struct Bignum{
    	int V[maxn],len;
    	Bignum(){memset(V,0,sizeof(V)),len=1;}
    	void init(){V[0]=1;}
    	void read(char *s){
    		int l=strlen(s),t=1;
    		reverse(s,s+l); len=(l-1)/digit+1;
    		for (int i=0;i<l;i++)	V[i/digit]+=(s[i]-'0')*t,t*=10,t%=base;
    	}
    	void write(){
    		printf("%d",V[len-1]);
    		for (int i=len-2;~i;i--)	printf("%0*d",digit,V[i]);
    		putchar('
    ');
    	}
    }F[maxn],S[maxn];
    Bignum operator +(Bignum x,Bignum y){
    	Bignum z; z.len=max(x.len,y.len);
    	for (int i=0;i<z.len;i++)	z.V[i]+=(x.V[i]+y.V[i]),z.V[i+1]+=z.V[i]/base,z.V[i]%=base;
    	while (z.V[z.len])	z.V[z.len+1]+=z.V[z.len]/base,z.V[z.len]%=base,z.len++;
    	return z;
    }
    Bignum operator -(Bignum x,Bignum y){
    	Bignum z; z.len=max(x.len,y.len);
    	for (int i=0;i<z.len;i++){
    		z.V[i]+=(x.V[i]-y.V[i]);
    		if (z.V[i]<0)	z.V[i]+=base,z.V[i+1]--;
    	}
    	while (!z.V[z.len]&&z.len>1)	z.len--;
    	while (z.V[z.len])	z.V[z.len+1]+=z.V[z.len]/base,z.V[z.len]%=base,z.len++;
    	return z;
    }
    Bignum operator *(Bignum x,Bignum y){
    	Bignum z; z.len=x.len+y.len;
    	for (int i=0;i<x.len;i++)
    		for (int j=0;j<y.len;j++)
    			z.V[i+j]+=x.V[i]*y.V[j],z.V[i+j+1]+=z.V[i+j]/base,z.V[i+j]%=base;
    	while (!z.V[z.len]&&z.len>1)	z.len--;
    	while (z.V[z.len])	z.V[z.len+1]+=z.V[z.len]/base,z.V[z.len]%=base,z.len++;
    	return z;
    }
    Bignum mlt(Bignum a,int b){
    	Bignum res; res.init();
    	for (;b;b>>=1,a=a*a)	if (b&1)	res=res*a;
    	return res;
    }
    int main(){
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	int n=read(0),d=read(0);
    	F[0].V[0]=1,F[1].V[0]=1;
    	S[0]=F[0],S[1]=F[0]+F[1];
    	for (int i=2;i<=d;i++){
    		F[i]=mlt(S[i-1],n)-mlt(S[i-2],n);
    		S[i]=S[i-1]+F[i];
    	}
    	F[d].write();
    	return 0;
    }
    
    作者:Wolfycz
    本文版权归作者和博客园共有,欢迎转载,但必须在文章开头注明原文出处,否则保留追究法律责任的权利
  • 相关阅读:
    设计模式(简述)
    sql注入防御
    两个防SQL注入过滤代码
    SQL注入实战利用“dbo”获得SQL管理权限和系统权限
    SQL注入技术和跨站脚本攻击的检测
    蓝雨设计整站SQL注入漏洞
    SQL注入攻击零距离
    菜鸟入门级:SQL注入攻击
    三步堵死SQL注入漏洞
    终极防范SQL注入漏洞
  • 原文地址:https://www.cnblogs.com/Wolfycz/p/14939155.html
Copyright © 2011-2022 走看看