【FJOI2007】bzoj1002 轮状病毒

    xiaoxiao2021-03-25  141

    Description

      轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子 和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道。如下图所示

      N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不 同的3轮状病毒,如下图所示   现给定n(N<=100),编程计算有多少个不同的n轮状病毒

    Input

      第一行有1个正整数n Output

      计算出的不同的n轮状病毒数输出

    用矩阵树定理long double精度过不了,只好上网搜到递推式 fi=3fi1fi2+2 。我也不知道为什么。

    #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int p=10000; struct big { int a[20],l; big operator + (const big &b) const { big ret; ret.a[1]=0; for (int i=1;i<=l||i<=b.l;i++) { ret.a[i]+=a[i]+b.a[i]; ret.a[i+1]=ret.a[i]/p; ret.a[i]%=p; } ret.l=max(l,b.l); if (ret.a[ret.l+1]) ret.l++; return ret; } big operator + (const int &x) const { big ret; ret.a[1]=x; for (int i=1;i<=l;i++) { ret.a[i]+=a[i]; ret.a[i+1]=ret.a[i]/p; ret.a[i]%=p; } ret.l=l; if (ret.a[ret.l+1]) ret.l++; return ret; } big operator - (const big &b) const { big ret; ret.a[1]=0; for (int i=1;i<=l;i++) { ret.a[i]+=a[i]-b.a[i]; if (ret.a[i]<0) { ret.a[i+1]=-1; ret.a[i]+=p; } else ret.a[i+1]=0; } ret.l=l; while (!ret.a[ret.l]) ret.l--; return ret; } big operator * (const int &x) const { big ret; ret.a[1]=0; for (int i=1;i<=l;i++) { ret.a[i]+=a[i]*x; ret.a[i+1]=ret.a[i]/p; ret.a[i]%=p; } ret.l=l; if (ret.a[ret.l+1]) ret.l++; return ret; } void out() { printf("%d",a[l]); for (int i=l-1;i;i--) { if (a[i]<1000) putchar('0'); if (a[i]<100) putchar('0'); if (a[i]<10) putchar('0'); printf("%d",a[i]); } putchar('\n'); } }f[110]; int n; int main() { scanf("%d",&n); f[1].l=f[1].a[1]=f[2].l=1; f[2].a[1]=5; for (int i=3;i<=n;i++) f[i]=f[i-1]*3-f[i-2]+2; f[n].out(); }
    转载请注明原文地址: https://ju.6miu.com/read-8620.html

    最新回复(0)