bzoj1089严格n元树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1089
这是一种套路:记录“深度为 i ”的话,转移需要讨论许多情况;所以可以记录成“深度<=i”!!!
(这种前缀和的样子得到答案也很方便,就是 f [ d ] - f [ d -1 ]。)
这样的话把根节点拿出来,剩下的就是n个深度为 i - 1 的子树了。
当然,每个深度的情况里要包含“什么节点也没有”的情况,才能正确转移。所以要+1。
1.重载运算符好方便! 2.输出的时候要注意不能吞0!学了一招。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int rad=1000; int n,d; struct data{ int v[5005],l; }f[30]; data operator*(data a,data b) { data c;c.l=a.l+b.l; for(int i=1;i<=c.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];//+= for(int i=1;i<=c.l;i++) if(c.v[i]>=rad) { if(i==c.l)c.l++,c.v[c.l]=0; c.v[i+1]+=c.v[i]/rad; c.v[i]%=rad; } while(!c.v[c.l]&&c.l>1)c.l--;//c.l>1 return c; } data operator^(data a,int b) { data c; c.v[1]=1;c.l=1; while(b) { if(b&1)c=c*a; a=a*a;b>>=1; } return c; } data operator+(data a,int b) { a.v[1]+=b;int k=1; while(a.v[k]>=rad)a.v[k+1]+=a.v[k]/rad,a.v[k]%=rad,k++; a.l=max(a.l,k); return a; } data operator-(data a,data b) { for(int i=a.l;i;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]&&a.l>1)a.l--; return a; } void print(data a) { printf("%d",a.v[a.l]); for(int i=a.l-1;i;i--)printf("%03d",a.v[i]); } int main() { scanf("%d%d",&n,&d); if(!d){printf("1");return 0;} f[0]=f[0]+1; for(int i=1;i<=d;i++) f[i]=(f[i-1]^n)+1; print(f[d]-f[d-1]); return 0; }