BZOJ 1002: [FJOI2007]轮状病毒

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 5764  Solved: 3131
[Submit][Status][Discuss]

Description

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

  N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不
同的3轮状病毒,如下图所示

  现给定n(N<=100),编程计算有多少个不同的n轮状病毒

Input

  第一行有1个正整数n

Output

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

Sample Input

3

Sample Output

16

HINT

 

Source

由基尔霍夫矩阵(没看懂)。。得 f[i]=f[i-1]*3-f[i-2]+2

套高精就过了

屠龙宝刀点击就送

#include <cstring>
#include <cstdio>
#define cl(a) memset(a,0,sizeof(a))
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define REP(a,b) for(;a&&b==0;--a)
#define Rep(a,b,c) for(int a=b;a<=c;++a)
#define ReP(a,b,c) for(int a=b;a>=c;--a)

struct node
{
    int a[100];
    node() {cl(a);}
    void output() {ReP(i,a[0],1) printf("%d",a[i]);}
}f[105];
inline node operator*(node a,int b)
{
    node c;
    c.a[0]=a.a[0]+1;
    rep(i,1,c.a[0]) c.a[i]=a.a[i]*b;
    int t=0;
    rep(i,1,c.a[0])
    {
        c.a[i]+=t;
        if(c.a[i]>=10) {t=c.a[i]/10,c.a[i]%=10;}
        else t=0;
    }
    REP(c.a[0],c.a[c.a[0]]);
    return c;
}
inline node operator-(node a,node b)
{
    node c;
    c.a[0]=a.a[0]+1;
    int i;
    Rep(i,1,a.a[0])
    {
        while(a.a[i]<b.a[i]) a.a[i]+=10,a.a[i+1]--;
        c.a[i]=a.a[i]-b.a[i];
    }
    REP(c.a[0],c.a[c.a[0]]);
    return c;
}
inline node operator+(node a,int b)
{
    node c=a;
    c.a[1]+=2;int i=1;
    while(c.a[i]>=10)
    {
        c.a[i+1]+=c.a[i]/10;
        c.a[i]%=10;
        ++i;
    }
    REP(c.a[0],c.a[c.a[0]]);
    return c;
}
int n;
int main()
{
    scanf("%d",&n);
    f[0].a[0]=1,f[1].a[0]=1,f[1].a[1]=1;
    rep(i,2,n)
     f[i]=f[i-1]*3,f[i]=f[i]-f[i-2],f[i]=f[i]+2;
    f[n].output();
    return 0;
}
原文地址:https://www.cnblogs.com/ruojisun/p/7643834.html