1089: [SCOI2003]严格n元树
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 872 Solved: 445
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
dp+高精度。
f[i]表示深度<=i的n元树有几种。
f[0]=1
f[i]=f[i-1]^n+1
这里的+1是加上深度为0的情况。
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; struct data { int l,v[1005]; }f[20]; int n,d; data operator *(data a,data b) { data ans; for (int i=1;i<=1000;i++) ans.v[i]=0; ans.l=0; for (int i=1;i<=1000;i++) ans.v[i]=0; for (int i=1000;i>=1001-b.l;i--) for (int j=1000;j>=1001-a.l;j--) ans.v[i-(1000-j)]+=(b.v[i]*a.v[j]); int now=1001-(a.l+b.l-1); for (int i=1000;i>now;i--) { if (ans.v[i]<10) continue; ans.v[i-1]+=(ans.v[i]/10); ans.v[i]%=10; } ans.l=a.l+b.l-1; while (ans.v[now]>=10) { ans.l++; ans.v[now-1]+=(ans.v[now]/10); ans.v[now]%=10; now--; } return ans; } data operator ^(data a,int x) { data ans; for (int i=1;i<=1000;i++) ans.v[i]=0; ans.l=1,ans.v[1000]=1; while (x) { if (x&1) ans=ans*a; a=a*a; x>>=1; } for (int i=1;i<=1000;i++) if (ans.v[i]) { ans.l=1001-i; break; } return ans; } data operator +(data a,int x) { a.v[1000]+=x; int now=1000; while (a.v[now]>=10) { a.v[now-1]+=(a.v[now]/10); a.v[now]%=10; now--; } for (int i=1;i<=1000;i++) if (a.v[i]) { a.l=1001-i; break; } return a; } data operator -(data a,data b) { for (int i=1000;i>=1001-a.l;i--) { a.v[i]-=b.v[i]; if (a.v[i]<0) a.v[i]+=10,a.v[i-1]--; } while (!a.v[1001-a.l]) a.l--; return a; } void Print(data a) { for (int i=1001-a.l;i<=1000;i++) printf("%d",a.v[i]); cout<<endl; } int main() { scanf("%d%d",&n,&d); f[0].l=1,f[0].v[1000]=1; for (int i=1;i<=d;i++) f[i]=(f[i-1]^n)+1; Print(f[d]-f[d-1]); return 0; }
感悟:
1.WA多次,是对于数字长度的处理出错了
2.一开始对于这道题想的是f[i]表示深度为i的n元树个数,发现很难转移;设成<=i的就方便多了
时间: 2024-10-06 06:44:44