bzoj1089严格n元树——DP+高精度
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1089
f[d]为深度小于等于d的树的个数;
从根节点出发,有n个子树,乘法原理可以得到 f[d] = f[d-1] ^ n + 1 ,加1是因为也可以没有根节点;
需要高精度,直接重载运算符十分方便。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const rad=1000; int n,d; struct data{ int v[5005],l; }f[30]; data operator*(data a,data b) { data c; for(int i=1;i<=a.l+b.l;i++)c.v[i]=0; for(int i=1;i<=a.l;i++) for(int j=1;j<=b.l;j++) c.v[i+j-1]+=a.v[i]*b.v[j]; c.l=a.l+b.l; for(int i=1;i<=c.l;i++) { if(c.v[i]>=rad) { if(i==c.l) { c.l++; c.v[c.l]=c.v[i]/rad; } else c.v[i+1]+=c.v[i]/rad; c.v[i]%=rad; } } while(c.v[c.l]==0&&c.l>1)c.l--; return c; } data operator^(data a,int n) { data c; c.l=1;c.v[1]=1; while(n) { if(n&1)c=c*a; a=a*a; n>>=1; } return c; } data operator+(data a,int x) { a.v[1]+=x; int now=1; while(a.v[now]>=rad)a.v[now+1]+=a.v[now]/rad,a.v[now]%=rad,now++; a.l=max(a.l,now); return a; } data operator-(data a,data b) { for(int i=1;i<=a.l;i++) { a.v[i]-=b.v[i]; if(a.v[i]<0) { a.v[i]+=rad; a.v[i+1]--; } } while(a.v[a.l]==0&&a.l>1)a.l--; return a; } //void print(data a) //{ // for(int i=a.l;i;i--) // printf("%d",a.v[i]); //} void print(data a) { printf("%d",a.v[a.l]); for(int i=a.l-1;i;i--) printf("%03d",a.v[i]); printf("\n"); } int main() { scanf("%d%d",&n,&d); if(d==0) { printf("1");return 0; } f[0].l=1;f[0].v[1]=1; for(int i=1;i<=d;i++) f[i]=(f[i-1]^n)+1;//+ 必须加括号!!! print(f[d]-f[d-1]); return 0; }