题目描述
轮状病毒有很多变种。许多轮状病毒都是由一个轮状基产生。一个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; }