【BZOJ1089】[SCOI2003]嚴格n元樹(高精度,動態規劃)
阿新 • • 發佈:2018-10-03
space mem www. ++ 只有一個 per ++i https 乘法
【BZOJ1089】[SCOI2003]嚴格n元樹(高精度,動態規劃)
題面
BZOJ
洛谷
題解
設\(f[i]\)表示深度為\(i\)的\(n\)元樹個數。然後我們每次加入一個根節點,然後枚舉它的子樹的深度乘起來就好了。但是這樣不好做,我們設\(f[i]\)表示深度至多為\(i\)的\(n\)元樹個數,那麽顯然,\(f[i]=f[i-1]^n+1\),加一的原因是存在只有一個根節點的情況。最終的答案直接容斥一下就變成了\(f[d]-f[d-1]\)。寫個高精度就好了,反正位數不多,乘法直接暴力就行。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,d; struct BigInt { int s[2000],ws; void init(){memset(s,0,sizeof(s));s[ws=1]=0;} void output(){for(int i=ws;i;--i)printf("%d",s[i]);puts("");} }f[20],One; BigInt operator+(BigInt a,BigInt b) { int ws=max(a.ws,b.ws); for(int i=1;i<=ws;++i)a.s[i]+=b.s[i]; for(int i=1;i<=ws;++i)a.s[i+1]+=a.s[i]/10,a.s[i]%=10; while(a.s[ws+1])++ws,a.s[ws+1]+=a.s[ws]/10,a.s[ws]%=10; a.ws=ws;return a; } BigInt operator-(BigInt a,BigInt b) { int ws=a.ws; for(int i=1;i<=b.ws;++i)a.s[i]-=b.s[i]; for(int i=1;i<=ws;++i)if(a.s[i]<0)a.s[i]+=10,a.s[i+1]-=1; while(!a.s[ws])--ws; a.ws=ws;return a; } BigInt operator*(BigInt a,BigInt b) { BigInt ret;int ws=a.ws+b.ws;ret.init(); for(int i=1;i<=a.ws;++i) for(int j=1;j<=b.ws;++j) ret.s[i+j-1]+=a.s[i]*b.s[j]; for(int i=1;i<=ws;++i)ret.s[i+1]+=ret.s[i]/10,ret.s[i]%=10; while(!ret.s[ws])--ws; ret.ws=ws;return ret; } BigInt fpow(BigInt a,int b) { BigInt s;s.init();s.s[1]=1; while(b){if(b&1)s=s*a;a=a*a;b>>=1;} return s; } int main() { cin>>n>>d;f[0].init();f[0].s[1]=1;One.init();One.s[1]=1; for(int i=1;i<=d;++i)f[i]=fpow(f[i-1],n)+One; f[d]=f[d]-f[d-1];f[d].output(); return 0; }
【BZOJ1089】[SCOI2003]嚴格n元樹(高精度,動態規劃)