【SCOI 2003】 严格n元树

【题目链接】

           点击打开链接

【算法】

          f[i]表示深度小于等于i的严格n元树

          显然,一棵深度小于等于i的严格n元树,就是一个根节点,下面有n棵子树,这n棵子树都是深度小于等于i-1的严格n元树,每棵子树有f[i-1]种形态,根据乘法原理,

          可知f[i] = f[i-1] ^ n + 1

          那么最后f[d] - f[d-1]就是答案

          注意要用高精度计算

【代码】

          

#include<bits/stdc++.h>
using namespace std;
#define MAXN 35
#define MAXL 400
 
int i,n,d;
struct INT
{
        int len;
        int num[MAXL];
} ans,f[MAXN];
 
inline INT add(INT x)
{
        int i;
        reverse(x.num,x.num+x.len); 
        x.num[0]++;
        for (i = 0; i < x.len; i++)
        {
                if (x.num[i] >= 10)
                {
                        x.num[i+1]++;
                        x.num[i] %= 10;
                }
        }
        while (x.num[x.len]) x.len++;
        reverse(x.num,x.num+x.len);
        return x;
}
inline void multipy(INT &a,INT b)
{
        int i,j;
        static INT res;
        memset(res.num,0,sizeof(res.num));
        reverse(a.num,a.num+a.len);
        reverse(b.num,b.num+b.len);
        for (i = 0; i < a.len; i++)
        {
                for (j = 0; j < b.len; j++)
                {
                        res.num[i+j] += a.num[i] * b.num[j];     
                }    
        }    
        res.len = a.len + b.len - 1;
        while (!res.num[res.len-1]) res.len--;
        for (i = 0; i < res.len; i++)
        {
                if (res.num[i] >= 10) 
                {
                        res.num[i+1] += res.num[i] / 10;
                        res.num[i] %= 10; 
                }
        }
        if (res.num[res.len]) res.len++;
        reverse(res.num,res.num+res.len);
        a = res;
}
inline INT _minus(INT a,INT b)
{
        static INT res;
        memset(res.num,0,sizeof(res.num));
        reverse(a.num,a.num+a.len);
        reverse(b.num,b.num+b.len);
        for (i = 0; i < a.len; i++)
        {
                if (a.num[i] >= b.num[i]) res.num[i] = a.num[i] - b.num[i];
                else
                {
                        a.num[i+1]--;
                        res.num[i] = a.num[i] + 10 - b.num[i];    
                } 
        }
        res.len = a.len;
        while (!res.num[res.len-1]) res.len--;
        reverse(res.num,res.num+res.len);
        return res;
}
inline INT power(INT a,int n)
{
        INT res;
        if (!n) return (INT){1,{1}};
        if (n == 1) return a;
        res = power(a,n>>1);
        multipy(res,res);
        if (n & 1) multipy(res,a);
        return res;    
}
inline void output(INT x)
{
        int i;
        for (i = 0; i < x.len; i++) printf("%d",x.num[i]);
        puts("");    
}

int main()
{
        
        scanf("%d%d",&n,&d);
        f[0] = (INT){1,{1}};
        for (i = 1; i <= d; i++) f[i] = add(power(f[i-1],n));
        ans = _minus(f[d],f[d-1]);
        output(ans);
    
        return 0;
}
    

 


posted @ 2018-05-15 21:20  evenbao  阅读(162)  评论(0编辑  收藏  举报