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;
}