1089: [SCOI2003]严格n元树

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 762  Solved: 387
[Submit][Status]

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

HINT

Source

题解:

先说一下此题我的想法(尽管没有A掉。。。)

考虑递推解此题:

设f[i]表示深度为i的严格n元树的数目,g[i]表示深度为(1--i)的严格n元树的数目。

则我们有如下递推式:

1.f[i]=g[i-1]^n-g[i-2]^n

2.g[i]=g[i-1]+f[i]

第二个是显然的,我们来说一下第一个是怎么来的。

因为我们从i-1递推到i,所以考率在n棵子树上加一个根节点,其余为原先的子树

因为要保证这棵树的深度达到n,所以至少有一个子树的深度达到n-1,

所以每个子树可以有g[i-1]种形态,n棵就是g[i-1]^n,然后去掉不合法的,

不合法的就是每个子树的深度都在1--i-2,即有g[i-2]种选择,也就是 g[i-2]^n

然后如果我们使用累加法的话可以发现 g[i]=g[i-1]^n+1,貌似很简单了?

TLE!!!尽管没有试,但我想是这样的,因为这个复杂度的话,ans必须<=4000位,看起来貌似不可能那么少。。。

高精度乘高精度太浪费时间了,我暂时没有想到好的解决办法。

贴一下上面的代码(没有用累加法)

  1. #include<cstdio>
  2.  
  3. #include<cstdlib>
  4.  
  5. #include<cmath>
  6.  
  7. #include<cstring>
  8.  
  9. #include<algorithm>
  10.  
  11. #include<iostream>
  12.  
  13. #include<vector>
  14.  
  15. #include<map>
  16.  
  17. #include<set>
  18.  
  19. #include<queue>
  20.  
  21. #include<string>
  22.  
  23. #define inf 1000000000
  24.  
  25. #define maxn 50
  26.  
  27. #define maxm 500000
  28.  
  29. #define eps 1e-10
  30.  
  31. #define ll long long
  32.  
  33. #define pa pair<int,int>
  34.  
  35. #define for0(i,n) for(int i=0;i<=(n);i++)
  36.  
  37. #define for1(i,n) for(int i=1;i<=(n);i++)
  38.  
  39. #define for2(i,x,y) for(int i=(x);i<=(y);i++)
  40.  
  41. #define for3(i,x,y) for(int i=(x);i>=(y);i--)
  42.  
  43. #define mod 10000
  44.  
  45. using namespace std;
  46.  
  47. inline int read()
  48.  
  49. {
  50.  
  51. int x=,f=;char ch=getchar();
  52.  
  53. while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
  54.  
  55. while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
  56.  
  57. return x*f;
  58.  
  59. }
  60. int n,m,f[maxn][maxm],g[][maxm],t[maxm],c[maxm];
  61. inline void writeln(int *a)
  62. {
  63. cout<<a[a[]];
  64. for3(i,a[]-,)cout<<a[i];cout<<endl;
  65. }
  66. inline void update(int *a)
  67. {
  68. for1(i,a[])
  69. {
  70. a[i+]+=a[i]/mod;
  71. a[i]%=mod;
  72. if(a[a[]+])a[]++;
  73. }
  74. }
  75. inline void mul(int *a,int x)
  76. {
  77. for1(i,a[])a[i]*=x;
  78. update(a);
  79. }
  80. inline void jia(int *a,int *b)
  81. {
  82. a[]=max(a[],b[]);
  83. for1(i,a[])
  84. {
  85. a[i]+=b[i];
  86. a[i+]+=a[i]/mod;
  87. a[i]%=mod;
  88. }
  89. while(!a[a[]])a[]--;
  90. }
  91. inline void cheng(int *a,int *b)
  92. {
  93. memset(c,,sizeof(c));
  94. for1(i,a[])
  95. for1(j,b[])
  96. {
  97. c[i+j-]+=a[i]*b[j];
  98. c[i+j]+=c[i+j-]/mod;
  99. c[i+j-]%=mod;
  100. }
  101. c[]=a[]+b[]+;
  102. while(!c[c[]]&&c[])c[]--;
  103. memcpy(a,c,sizeof(c));
  104. }
  105. inline void jian(int *a,int *b)
  106. {
  107. for1(i,a[])
  108. {
  109. a[i]-=b[i];
  110. if(a[i]<)a[i]+=mod,a[i+]-=;
  111. }
  112. while(!a[a[]])a[]--;
  113. }
  114.  
  115. int main()
  116.  
  117. {
  118.  
  119. freopen("input.txt","r",stdin);
  120.  
  121. freopen("output.txt","w",stdout);
  122.  
  123. n=read();m=read();
  124. f[][f[][]=]=;
  125. g[][g[][]=]=;
  126. g[][g[][]=]=;
  127. for2(i,,m)
  128. {
  129. f[i][f[i][]=]=;
  130. for1(j,n)cheng(f[i],g[]);
  131. t[t[]=]=;
  132. for1(j,n)cheng(t,g[]);
  133. jian(f[i],t);
  134. jia(g[],f[i-]);
  135. jia(g[],f[i]);
  136. }
  137. printf("%d",f[m][f[m][]]);
  138. for3(i,f[m][]-,)printf("%04d",f[m][i]);
  139.  
  140. return ;
  141.  
  142. }

感觉不会再爱了,这居然就是正解QAQ

不会貌似别人解释的更简单,直接推g[i]的表达式也很简单。

妈蛋,数据范围给的太大了,和lydsy要过来数据发现全是非常小的T_T

我做了2天多,一直在对拍自己的程序为什么出错,AC的程序运行过程中答案为什么会越来越小,我的程序为什么10 15的点都跑不出来,而且位数剧增

今天才发现是别人的空间爆了啊。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

还以为是我的程序错了啊。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

看来我的推断没有错,如果数据范围真如题中所说,那么答案的位数就太大了。

我要去建议lydsy修改此题的题面,不要再像坑我一样坑了其他人。。。

代码:

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<algorithm>
  6. #include<iostream>
  7. #include<vector>
  8. #include<map>
  9. #include<set>
  10. #include<queue>
  11. #include<string>
  12. #define inf 1000000000
  13. #define maxn 500+100
  14. #define maxm 500+100
  15. #define eps 1e-10
  16. #define ll long long
  17. #define pa pair<int,int>
  18. #define for0(i,n) for(int i=0;i<=(n);i++)
  19. #define for1(i,n) for(int i=1;i<=(n);i++)
  20. #define for2(i,x,y) for(int i=(x);i<=(y);i++)
  21. #define for3(i,x,y) for(int i=(x);i>=(y);i--)
  22. #define mod 10000
  23. using namespace std;
  24. inline int read()
  25. {
  26. int x=,f=;char ch=getchar();
  27. while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
  28. while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();}
  29. return x*f;
  30. }
  31. class bigg
  32. {
  33. public:
  34. int num[maxn], len;
  35. bigg()
  36. {
  37. memset(num,,sizeof(num));
  38. len=;
  39. }
  40. bigg operator = (const bigg &b)
  41. {
  42. memset(num,,sizeof(num));
  43. len=b.len;
  44. for1(i,len)num[i]=b.num[i];
  45. return(*this);
  46. }
  47. bigg operator = (int b)
  48. {
  49. memset(num,,sizeof());
  50. if (b==)
  51. {
  52. len=;
  53. return(*this);
  54. }
  55. len=;
  56. while(b>)
  57. {
  58. num[++len]=b%mod;
  59. b/=mod;
  60. }
  61. return (*this);
  62. }
  63. bigg operator * (const bigg &b)
  64. {
  65. bigg ans;
  66. ans=;
  67. if (len==&&num[]==||b.len==&&b.num[]==)
  68. return ans;
  69. ans.len=len+b.len-;
  70. for1(i,len)
  71. for1(j,b.len)
  72. {
  73. ans.num[i+j-]+=num[i]*b.num[j];
  74. ans.num[i+j]+=ans.num[i+j-]/mod;
  75. ans.num[i+j-]%=mod;
  76. }
  77. if (ans.num[ans.len+])ans.len++;
  78. while(!ans.num[ans.len])ans.len--;
  79. return ans;
  80. }
  81. bigg operator - (const bigg &b)
  82. {
  83. bigg ans;
  84. ans=;
  85. ans.len=len;
  86. for1(i,len)
  87. {
  88. ans.num[i]+=num[i]-b.num[i];
  89. if (ans.num[i]<)
  90. {
  91. ans.num[i+]--;
  92. ans.num[i]+=mod;
  93. }
  94. }
  95. while (ans.len>&&!ans.num[ans.len]) ans.len--;
  96. return ans;
  97. }
  98. bigg operator + (const bigg &b)
  99. {
  100. bigg ans;
  101. ans=;
  102. ans.len=max(len,b.len);
  103. for1(i,ans.len)
  104. {
  105. ans.num[i]+=num[i]+b.num[i];
  106. ans.num[i+]=ans.num[i]/mod;
  107. ans.num[i]%=mod;
  108. }
  109. if (ans.num[ans.len+])ans.len++;
  110. return ans;
  111. }
  112. void print()
  113. {
  114. printf("%d",num[len]);
  115. for3(i,len-,)printf("%04d",num[i]);
  116. printf("\n");
  117. }
  118. };
  119.  
  120. int main()
  121. {
  122. freopen("input.txt","r",stdin);
  123. freopen("output.txt","w",stdout);
  124. int n, deep;
  125. scanf("%d%d", &n, &deep);
  126. if (deep == )
  127. {
  128. printf("1\n");
  129. return ;
  130. }
  131. bigg fpre, fnow, f1;
  132. fpre=,f1=;
  133. for1(i,deep)
  134. {
  135. fnow=;
  136. for1(j,n)fnow=fnow*fpre;
  137. fnow=fnow+f1;
  138. if (i!= deep) fpre=fnow;
  139. }
  140. fnow=fnow-fpre;
  141. fnow.print();
  142. return ;
  143. }

不过还是有几点收获的:

1.捞到一个高精度模版

2.class里数组要开小

BZOJ1089: [SCOI2003]严格n元树的更多相关文章

  1. bzoj1089 [SCOI2003]严格n元树(dp+高精)

    1089: [SCOI2003]严格n元树 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1899  Solved: 954[Submit][Statu ...

  2. [BZOJ1089][SCOI2003]严格n元树(递推+高精度)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1089 分析: 第一感觉可以用一个通式求出来,但是考虑一下很麻烦,不好搞的.很容易发现最 ...

  3. BZOJ1089:[SCOI2003]严格n元树(DP,高精度)

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

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

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

  5. 【BZOJ1089】[SCOI2003]严格n元树(高精度,动态规划)

    [BZOJ1089][SCOI2003]严格n元树(高精度,动态规划) 题面 BZOJ 洛谷 题解 设\(f[i]\)表示深度为\(i\)的\(n\)元树个数.然后我们每次加入一个根节点,然后枚举它的 ...

  6. BZOJ 1089: [SCOI2003]严格n元树

    1089: [SCOI2003]严格n元树 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1591  Solved: 795[Submit][Statu ...

  7. bzoj 1089 [SCOI2003]严格n元树(DP+高精度)

    1089: [SCOI2003]严格n元树 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1250  Solved: 621[Submit][Statu ...

  8. SCOI2003 严格N元树

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

  9. 【BZOJ】1089: [SCOI2003]严格n元树(递推+高精度/fft)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1089 题意:求深度为d的n元树数目.(0<n<=32, 0<=d<=16) ...

随机推荐

  1. Android笔记(三):View一些值得注意的地方

    Button android:textAllCaps="false" // Button上的英文字符不转成大写 EditText android:maxLines="2& ...

  2. (转)利用ant在Mac 下自动化打包签名Android程序

    1.创建一个android项目 参数说明:-k /--package 为命名空间(包名)-a /--name 工程名-p /--path 项目 -t 为目标平台的版本编号 命令:./android c ...

  3. 深入解读ESB与SOA的关系

    时至今日,SOA的概念渐渐清晰了.   有关ESB的概念,已经吵了好多年了,还是没有定论. 我个人认为,ESB本来就是抽象的概念,而且内涵丰富,在不同的场合含义不同.因此应该从不同的角度来认识.   ...

  4. UVA10765-Doves and bombs(BCC)

    option=com_onlinejudge&Itemid=8&page=show_problem&problem=1706">题目链接 题意:给定一个n个点的 ...

  5. Java基础知识强化59:String(字符串)和其他类型的相互转化

    1. String类型 ---> 其他类型 (1)使用基本类型包装类的parseXXX方法 e.g:String(字符串)转化为int(整型) String MyNumber ="12 ...

  6. asp.net 5.0微信支付

    (原文出自:http://lib.csdn.net/article/wechat/46329) 微信支付官方坑太多,我们来精简 我把官方的代码,打包成了 an.wxapi.dll. 里面主要替换了下注 ...

  7. html 文字溢出标签

    overflow:visible;作用:能看到溢出部分. overflow: hidden;作用:溢出部分看不到 overflow:scroll; 作用:出现一个滚动条(不超过的文字也会在滚动条里) ...

  8. 2:numpy---ndarray

    ndarray即是多维数组[n dimension array] 一:创建ndarray 有好几种创建数组的方法. 例如,你可以使用 array 函数从常规的Python列表和元组创造数组.所创建的数 ...

  9. (转)asp.net注册实现下一步

    在asp.net中有两种容器控件,其中包括panel和placeholder控件. 使用panel控件可以对控件进行分组.一帮助组织web窗体也的内容,将控件组织在面板中,可提供有关在运行时控件应如何 ...

  10. Swift缩水版MJExtension - Reflect的基本使用

    github:https://github.com/CharlinFeng/Reflect 直接拖拽Reflect文件夹到您的项目中即可,无任何第三方依赖!文件夹结构说明:.Coding 归档相关.R ...