BZOJ_1002_[FJOI2007]_轮状病毒_(递推+高精)
描述
http://www.lydsy.com/JudgeOnline/problem.php?id=1002
)*&*(^&*^&*^**()*)
1002: [FJOI2007]轮状病毒
Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4060 Solved: 2239
[Submit][Status][Discuss]
Description
轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子
和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道。如下图所示
N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不
同的3轮状病毒,如下图所示
现给定n(N<=100),编程计算有多少个不同的n轮状病毒
Input
第一行有1个正整数n
Output
计算出的不同的n轮状病毒数输出
Sample Input
3
Sample Output
16
HINT
Source
分析
题目是求一种特殊的图的生成树的个数,但是貌似有更一般的算法,等明天再看吧...
只搞懂了打表找规律,然后题推的解法.
随便写个暴力打个表(其实我并不会写,明天再写吧今天好累),找一找规律.
1~14的答案如下
1 5 16 45 121 320 841 2205 5776 15125 39601 103680 271441 710645
奇数项
1 16 121 841 5776 39601 271441
开根号得
1 4 11 29 76 199 521
a[i]=a[i-1]*3-a[i-2]
偶数项
5 45 320 2205 15125 103680 710645
除以5得
1 9 64 441 3025 20736 142129
开根号得
1 3 8 21 55 144 377
a[i]=a[i-1]*3-a[i-2]
注意要用高精(学习了别人的高精写法,自己写得太小学生了)
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 struct Big_Integer{ 6 int x[100],cnt; 7 int & operator [] (int id){ 8 return x[id]; 9 } 10 void operator = (int y){ 11 x[1]=y; 12 cnt=1; 13 } 14 }f[100]; 15 Big_Integer operator - (Big_Integer x,Big_Integer y){ 16 Big_Integer z=f[0]; 17 z.cnt=max(x.cnt,y.cnt); 18 for(int i=1;i<=z.cnt;i++){ 19 z[i]+=x[i]-y[i]; 20 if(z[i]<0) z[i+1]--, z[i]+=10; 21 } 22 while(z.cnt&&!z[z.cnt]) z.cnt--; 23 return z; 24 } 25 Big_Integer operator * (Big_Integer x,Big_Integer y){ 26 Big_Integer z=f[0]; 27 for(int i=1;i<=x.cnt;i++){ 28 for(int j=1;j<=y.cnt;j++){ 29 z[i+j-1]+=x[i]*y[j],z[i+j]+=z[i+j-1]/10,z[i+j-1]%=10; 30 } 31 } 32 z.cnt=x.cnt+y.cnt; 33 if(!z[z.cnt]) z.cnt--; 34 return z; 35 } 36 Big_Integer operator * (Big_Integer x,int y){ 37 Big_Integer z=f[0]; 38 for(int i=1;i<=x.cnt;i++){ 39 z[i]+=x[i]*y,z[i+1]+=z[i]/10,z[i]%=10; 40 } 41 z.cnt=x.cnt; 42 if(z[z.cnt+1]) z.cnt++; 43 return z; 44 } 45 ostream& operator << (ostream &out,Big_Integer x){ 46 for(int i=x.cnt;i;i--){ 47 out << x[i]; 48 } 49 return out; 50 } 51 int n; 52 int main(){ 53 cin >> n; 54 f[1]=1; 55 f[2]=n&1?4:3; 56 int last=n+1>>1; 57 for(int i=3;i<=last;i++){ 58 f[i]=f[i-1]*3-f[i-2]; 59 } 60 cout << f[last]*f[last]*(n&1?1:5) << endl; 61 return 0; 62 }