SCOI2003【严格n元树】
来源:互联网 发布:一键安装java环境 编辑:程序博客网 时间:2024/06/05 15:46
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元树的数目。
如果一棵树的所有非叶节点都恰好有n个儿子,那么我们称它为严格n元树。如果该树中最底层的节点深度为d(根的深度为0),那么我们称它为一棵深度为d的严格n元树。例如,深度为2的严格2元树有三个,如下图:
给出n, d,编程数出深度为d的n元树数目。
仅包含两个整数n, d( 0 < n < = 32, 0 < = d < = 16)
仅包含一个数,即深度为d的n元树的数目。
我是先从简单的情况入手,就讨论完全二叉树的个数,得到是2^2n -1
然后又想完全三叉树的个数
然后就陷入了一个误区:总是想考虑下面的叶子节点该怎么加才满足,使劲推公式尽量往组合数上靠,结果憋了半天没搞出来。
然后题解是dp:
定义f[i]表示深度为i的n元树的个数,发现这个并不好直接转移
因为组合的时候不一定是一些i-1深度的n元树。
需要转化:
改为求f[i]的前缀和s[i]
s[i]表示深度不大于i的n元树的个数.
这里转移不是考虑怎么在下面加节点,而是添一个根:
s[i-1]种不同的n元树,在添一个根时候的状态是n棵不同的不超过i-1深度的树排在一起,也有可能为空.
s[i]=s[i-1]^n +1(我们考虑树不为空的情况,但组合的时候可能只有根,而s[i-1]状态里没有空的子树)
然后答案就是s[i]-s[i-1]了。
这里吸取一个教训,不要局限于题意顺序,逆向思维。
#include<cstdio>#include<iostream>#include<cstring>#include<cstdlib>#include<algorithm>#include<queue>#include<cmath>#define base 10000#define maxlen 101#define get(x) (x-'0')using namespace std;int n,d;const int maxn=20;struct bign{int sign,len;int c[maxlen];bign(){sign=0;len=1;memset(c,0,sizeof(c));}void Printf(){if(sign)printf("-");printf("%d",c[len]);for(int i=len-1;i>=1;i--)printf("%04d",c[i]);printf("\n");}void zero(){while(len-1&&!c[len])len--;}void writen(char *s){int l=strlen(s),lim=0,k=1;if(s[0]=='-'){sign=1;lim=1;}for(int i=l-1;i>=lim;i--){c[len]+=get(s[i])*k;k*=10;if(k==base){len++;k=1;}}}void Read(){char s[maxlen*base];scanf("%s",s);writen(s);}bool operator <(const bign &b){if(len!=b.len)return len<b.len;for(int i=len;i>=1;i--){if(c[i]!=b.c[i])return c[i]<b.c[i];}return false;}bign operator =(const int &a){char s[maxlen*base];sprintf(s,"%d",a);writen(s);return *this;}bign operator +(const bign &b){bign r;r.len=max(len,b.len)+1;for(int i=1;i<=r.len;i++){r.c[i]+=c[i]+b.c[i];r.c[i+1]+=r.c[i]/base;r.c[i]%=base;}r.zero();return r;}bign operator +(const int &a){bign b;b=a;return *this+b;}bign operator *(const bign &b){bign r;r.len=len+b.len+2;for(int i=1;i<=len;i++){for(int j=1;j<=b.len;j++){r.c[i+j-1]+=c[i]*b.c[j];r.c[i+j]+=r.c[i+j-1]/base;r.c[i+j-1]%=base;}}r.zero();return r;}bign operator *(const int &a){bign b;b=a;return *this*b;}bign operator ^(const int &y){bign res;bign r=*this;res=1;int t=y;while(t){if(t&1)res=res*r;t>>=1;r=r*r;}return res;}bign operator -(const bign &b){bign r=*this;bign y=b;if(r<y)swap(r,y);for(int i=1;i<=r.len;i++){r.c[i]-=y.c[i];if(r.c[i]<0){r.c[i]+=base;r.c[i+1]--;}}return r;}}f[maxn];//f[i]表示深度不超过i的n元树的个数 int main(){scanf("%d%d",&n,&d);//f[i]=f[i-1]^n+1f[0]=1;for(int i=1;i<=d;i++)f[i]=(f[i-1]^n)+1;if(d==0)printf("1\n");else{bign ans=f[d]-f[d-1];ans.Printf();}return 0;}
1 0
- SCOI2003【严格n元树】
- 【题解】[scoi2003]严格n元树
- 【BZOJ 1089】 [SCOI2003]严格n元树
- 【SCOI2003】【BZOJ1089】严格n元树
- 1089: [SCOI2003]严格n元树
- bzoj1089-[SCOI2003]严格n元树
- 1089: [SCOI2003]严格n元树
- bzoj1089: [SCOI2003]严格n元树
- 1089: [SCOI2003]严格n元树
- bzoj1089 [SCOI2003]严格n元树
- [BZOJ1089][SCOI2003][递推][高精度]严格n元树
- BZOJ 1089 SCOI2003 严格n元树 动态规划+高精度
- 【BZOJ1089】[SCOI2003]严格n元树【递推】【高精度】
- 1089: [SCOI2003]严格n元树 DP+高精度
- bzoj 1089 [SCOI2003]严格n元树(DP+高精度)
- BZOJ1089——[SCOI2003]严格n元树
- bzoj 1089: [SCOI2003]严格n元树 (dp+高精度)
- BZOJ 1089: [SCOI2003]严格n元树 递推,高精度
- android大讲堂——listview详解
- URL中带加号的处理
- Java设计模式——原型模式
- linux sed指令的替换操作
- IOS中的几种比较常见的延时方法的介绍及各自优缺点
- SCOI2003【严格n元树】
- Android gradle配置
- 【vijos】P1911 珠心算测验
- ios常用的语法大全
- #pragma weak
- PIC C语言编程_PICC中变量修饰关键词
- 去除多余cell的线
- c 字符串函数
- 提取身份证中的年龄和性别