题目描述
轮状病毒有很多变种。许多轮状病毒都是由一个轮状基产生。一个n轮状基由圆环上n个不同的基原子和圆心的一个核原子构成。2个原子之间的边表示这2个原子之间的信息通道,如图1。
n轮状病毒的产生规律是在n轮状基中删除若干边,使各原子之间有唯一一条信息通道。例如,共有16个不同的3轮状病毒,入图2所示。
给定n(N<=100),编程计算有多少个不同的n轮状病毒。
输入输出格式
输入格式:
第一行有1个正整数n。
输出格式:
将编程计算出的不同的n轮状病毒数输出
输入输出样例
输入样例#1: 复制
3
输出样例#1: 复制
16
所以这道题想了很久,没有发现什么规律。然后去学(tou)习(kan)了一(ti)下(jie),发现有个仁兄硬是画出了n = 1~5的情况(1, 5, 16, 45, 121)………………发现n为偶数时答案形如x*x-4,n为奇数答案形如x*x。并且x[1] = 1,x[2] = 3,x[i] = x[i - 1] + x[i - 2],类似斐波那契数列。那么我们就可以递推推出答案了。(高精度封装结构体已经放在分享中)
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #define LL long long using namespace std; int n; namespace BIGINT { #define LL long long struct INT1024 { int len; int s[1030]; INT1024() {clean();} void clean() {memset(s, 0, sizeof(s)), len = 0;} void operator = (int x) { for(; x; x /= 10) s[len++] = x % 10; } void print() { for(int i = len - 1; i >= 0; --i) printf("%d", s[i]); putchar('\n'); } }; INT1024 c; INT1024 operator + (INT1024 a, INT1024 b) { int len = max(a.len, b.len); c.clean(); c.len=len; for(int i = 0;i < len; ++i) c.s[i] = a.s[i] + b.s[i]; for(int i = 0;i < len; ++i) c.s[i + 1] += c.s[i] / 10, c.s[i] %= 10; if(c.s[len]) ++c.len; return c; } INT1024 operator - (INT1024 a, INT1024 b) { c.clean(); for(int i = 0; i < a.len; ++i) { c.s[i] += a.s[i] - b.s[i]; if(c.s[i] < 0) c.s[i] += 10, --a.s[i + 1]; } int len = a.len - 1; for(; !c.s[len]; --len); c.len = len + 1; return c; } INT1024 operator * (INT1024 a, INT1024 b) { int len = a.len + b.len - 1; c.clean(); c.len = len; for(int i = 0;i < a.len; ++i) for(int j = 0; j < b.len; ++j) c.s[i + j] += a.s[i] * b.s[j]; for(int i = 0;i < len; ++i) c.s[i + 1] += c.s[i] / 10, c.s[i] %= 10; if(c.s[len]) ++c.len; return c; } } using namespace BIGINT; INT1024 f[105]; int main() { f[1] = 1, f[2] = 3; scanf("%d", &n); for(register int i = 3; i <= n; ++i) f[i] = f[i - 1] + f[i - 2]; INT1024 Lint = f[n] * f[n]; INT1024 Four; Four = 4; if(n & 1) Lint.print(); else Lint = Lint - Four, Lint.print(); return 0; }
没有帐号? 立即注册