【FJOI2007】轮状病毒 - Matrix-Tree定理

题目描述

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

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

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

输入输出格式

输入格式:

第一行有1个正整数n。

输出格式:

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

思路

根据Matrix-Tree定理,推出 $ f_{n} = f_{n-2} \times 3 - f_{n-1} + 2 $

至于证明博主太菜还不会,需要高精

#include <bits/stdc++.h>
using namespace std;
struct bign {
    int d[100], len;
    void clean() { while(len > 1 && !d[len-1]) len--; }
    bign() { memset(d, 0, sizeof(d)); len = 1; }
    bign(int num) { *this = num; }
    bign(char* num) { *this = num; }
    bign operator = (const char* num) {
        memset(d, 0, sizeof(d)); len = strlen(num);
        for(int i = 0; i < len; i++) d[i] = num[len-1-i] - '0';
        clean();
        return *this;
    }
    bign operator = (int num){
        char s[20]; sprintf(s, "%d", num);
        *this = s;
        return *this;
    }
    bign operator + (const bign& b){
        bign c = *this; int i;
        for (i = 0; i < b.len; i++){
            c.d[i] += b.d[i];
            if (c.d[i] > 9) c.d[i]%=10, c.d[i+1]++;
        }
        while (c.d[i] > 9) c.d[i++]%=10, c.d[i]++;
        c.len = max(len, b.len);
        if (c.d[i] && c.len <= i) c.len = i+1;
        return c;
    }
    bign operator - (const bign& b){
        bign c = *this; int i;
        for (i = 0; i < b.len; i++){
            c.d[i] -= b.d[i];
            if (c.d[i] < 0) c.d[i]+=10, c.d[i+1]--;
        }
        while (c.d[i] < 0) c.d[i++]+=10, c.d[i]--;
        c.clean();
        return c;
    }  
    bign operator * (const bign& b)const{
        int i, j; bign c; c.len = len + b.len;
        for(j = 0; j < b.len; j++) for(i = 0; i < len; i++)
            c.d[i+j] += d[i] * b.d[j];
        for(i = 0; i < c.len-1; i++)
            c.d[i+1] += c.d[i]/10, c.d[i] %= 10;
        c.clean();
        return c;
    }
}a,b,c;
int main() {
    int n;
    scanf("%d",&n);
    b = 5,c = 1;
    if (n < 3) {
        printf("%d",n == 2 ? 5 : 1);
        return 0;
    }
    for (int i = 3;i <= n;i++) {
        a = b*3-c+2;
        c = b;
        b = a;
    }
    for (int i = a.len-1;i >= 0;i--) printf("%d",a.d[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lrj124/p/8971219.html