• BZOJ1089 [SCOI2003]严格n元树 【dp + 高精】


    Description

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

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

    Input

      仅包含两个整数n, d( 0   <   n   <   =   32,   0  < =   d  < = 16)

    Output

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

    Sample Input

    【样例输入1】
    2 2

    【样例输入2】
    2 3

    【样例输入3】
    3 5

    Sample Output

    【样例输出1】
    3

    【样例输出2】
    21

    【样例输出2】
    58871587162270592645034001



    题解

    设f[d]为深度不大于d的n元树的个数,显然答案就是f[d] - f[d - 1]

    对于考虑f[d]的根节点,它的每一棵子树方案数都是f[d - 1],用乘法原理:

    f[d] = f[d - 1] ^ n + 1【+1考虑只有一个根节点】

    边界:f[0] = 1


    再者就是高精【好久没写高精乘高精了】,写的时候还需要先调一下


    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define fo(i,x,y) for (int i = (x); i <= (y); i++)
    #define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
    using namespace std;
    const int maxn = 20,maxm = 205,INF = 1000000000;
    
    int N,D;
    
    struct NUM{
    	int n[maxm],len;
    	NUM() {memset(n,0,sizeof(n)); len = 0;}
    }f[maxn];
    
    inline istream& operator >>(istream& in,NUM& a){
    	string s;
    	in>>s;
    	a.len = s.length();
    	for (int i = 0; i < a.len; i++) a.n[i] = s[a.len - i - 1] - '0';
    	return in;
    }
    
    inline ostream& operator << (ostream& out,const NUM& a){
    	if (!a.len) out<<0;
    	else {
    		for (int i = a.len - 1; i >= 0; i--) out<<a.n[i];
    	}
    	return out;
    }
    
    inline NUM operator *(const NUM& a,const NUM& b){
    	NUM c;
    	c.len = a.len + b.len + 2;
    	int carry = 0,temp;
    	for (int i = 0; i < a.len; i++){
    		for (int j = 0; j < b.len; j++){
    			temp = c.n[j + i] + a.n[i] * b.n[j] + carry;
    			c.n[j + i] = temp % 10;
    			carry = temp / 10;
    		}
    		int len = i + b.len;
    		while (carry) {
    			temp = c.n[len] + carry;
    			c.n[len] = temp % 10;
    			carry = temp / 10;
    			len++;
    		}
    	}
    	while (!c.n[c.len - 1]) c.len--;
    	return c;
    }
    
    inline NUM operator + (const NUM& a,const int& b){
    	NUM c = a;
    	int temp = c.n[0] + b,carry = temp / 10;
    	c.n[0] = temp % 10;
    	for (int i = 1; carry && i < c.len; i++){
    		temp = c.n[i] + carry;
    		c.n[i] = temp % 10;
    		carry = temp / 10;
    	}
    	if (carry) c.n[c.len++] = carry;
    	return c;
    }
    
    inline NUM operator - (const NUM& a,const NUM& b){
    	NUM c;
    	c.len = a.len;
    	int carry = 0;
    	for (int i = 0; i < a.len; i++){
    		c.n[i] = a.n[i] - b.n[i] + carry;
    		if (c.n[i] < 0) c.n[i] += 10,carry = -1;
    		else carry = 0;
    	}
    	while (!c.n[c.len - 1]) c.len--;
    	return c;
    }
    
    inline NUM qpow(NUM a,int b){
    	NUM ans; ans.n[0] = ans.len = 1;
    	for (; b; b >>= 1,a = a * a)
    		if (b & 1) ans = ans * a;
    	return ans;
    }
    
    int main()
    {
    	/*cin>>f[0]>>f[1];
    	cout<<f[0] * f[1]<<endl;*/
    	
    	cin>>N>>D;
    	if (!D) {cout<<1<<endl;return 0;}
    	f[0].n[0] = f[0].len = 1;
    	for (int i = 1; i <= D; i++){
    		f[i] = qpow(f[i - 1],N) + 1;
    	}
    	cout<<f[D] - f[D - 1]<<endl;
    	return 0;
    }
    

  • 相关阅读:
    C++中头文件包含的问题
    linux环境变量
    win32进程和线程
    断言
    win32中的常用类型转换
    可变形参
    #define
    CString与char*互相转化
    extern
    手机CPU和GPU厂商
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282836.html
Copyright © 2020-2023  润新知