bzoj1002:[FJOI2007]轮状病毒
思路:一道很裸的生成树计数问题,然而要高精度,而且听说直接行列式求值会被卡精度,所以可以模拟行列式求值的过程得到递推公式:f[i]=3*f[i-1]-f[i-2]+2,证明详见vfk博客:
http://vfleaking.blog.163.com/blog/static/17480763420119685112649/
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define maxn 105 #define mod 100000000 int n; struct bignum{ int len; int a[maxn*10]; bool operator <(const bignum &b)const{ if (len!=b.len) return len<b.len; for (int i=len;i;i--) if (a[i]<b.a[i]) return 1; return 0; } bignum operator +(const bignum &b){ bignum c;c.len=max(len,b.len);memset(c.a,0,sizeof(c.a)); for (int i=1;i<=c.len;i++){ c.a[i]+=a[i]+b.a[i]; if (c.a[i]>mod) c.a[i+1]=c.a[i]/mod,c.a[i]%=mod; } if (c.a[c.len+1]) c.len++; return c; } bignum operator -(const bignum &b){ bignum c;c.len=max(len,b.len);memset(c.a,0,sizeof(c.a)); for (int i=1;i<=c.len;i++){ c.a[i]=a[i]-b.a[i]; if (c.a[i]<0) c.a[i]+=mod,a[i+1]--; } for (;!c.a[c.len]&&c.len>1;c.len--); return c; } void initialize(char *s){ int l=strlen(s+1); for (int i=l;i>=1;i-=8){ len++;int x=pow(10,min(i-1,7)),t=max(i-8+1,1); while (x) a[len]+=(s[t]-'0')*x,t++,x/=10; } } void print(){ printf("%d",a[len]); for (int i=len-1;i;i--) printf("%08d",a[i]); } }f[maxn],t; int main(){ scanf("%d",&n);f[1].a[1]=1,f[1].len=1,f[2].a[1]=5,f[2].len=1,t.a[1]=2,t.len=1; for (int i=3;i<=n;i++) f[i]=f[i-1]+f[i-1]+f[i-1]-f[i-2]+t; f[n].print(); return 0; }