BZOJ 1002: [FJOI2007]轮状病毒【数学题】

1002: [FJOI2007]轮状病毒

时间限制: 1 Sec 内存限制: 162 MB

【题目描述】

  轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道。如下图所示
这里写图片描述
  N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不同的3轮状病毒,如下图所示
这里写图片描述

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

【输入格式】

  第一行有1个正整数n

【输出格式】

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

【输入样例】

3

【输出样例】

16

【解题报告】

本人也是推了半天,手动画出n=1~4的结(累死宝宝了,呼)

n 1 2 3 4
ans 1 5 16 45

好不容易推完n=4,突然发现数据太少,找到好几个规律。。。
最后还是上网查的:
f[i]=f[i-1]*3-f[i-2]+2
这题明显是要套高精度的,所以,我强忍着怒火(用mod会死啊!!!),码下了这段代码:

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int tt=10000;
int n;
struct xcw{
    int len,a[1005];
    xcw(){memset(a,0,sizeof(a));len=0;}
    xcw(int x){
        memset(a,0,sizeof(a));len=0;
        do{a[++len]=x%tt;x/=tt;}while(x);
    }
    xcw operator *(const int b)const{
        xcw c;
        c.len=len;
        for(int i=1;i<=len;i++){
            c.a[i]+=a[i]*b;
            c.a[i+1]+=c.a[i]/tt;
            c.a[i]%=tt;
        }
        if(c.a[c.len+1]) c.len++;
        return c;
    }
    xcw operator -(const xcw b)const{
        xcw c;
        c.len=max(len,b.len);
        for(int i=1;i<=c.len;i++){
            c.a[i]+=a[i]-b.a[i]+tt;
            c.a[i+1]+=c.a[i]/tt-1;
            c.a[i]%=tt;
        }
        while(!c.a[c.len]) c.len--;
        return c;
    }
    xcw operator +(const int b)const{
        xcw c;
        c.len=len;c.a[1]+=b;
        for(int i=1;i<=c.len;i++){
            c.a[i]+=a[i];
            c.a[i+1]+=c.a[i]/tt;
            c.a[i]%=tt;
        }
        if(c.a[c.len+1]) c.len++;
        return c;
    }
    void write(){
        printf("%d",a[len]);
        for(int i=len-1;i;i--) printf("%04d",a[i]);
        printf("\n");
    }
}f[105];
int main(){
    scanf("%d",&n);
    f[1]=1;f[2]=5;
    for(int i=3;i<=n;i++) f[i]=f[i-1]*3-f[i-2]+2;
    f[n].write();
    return 0;
}
posted @ 2017-12-21 19:10  XSamsara  阅读(126)  评论(0编辑  收藏  举报