BZOJ 1002 [FJOI2007]轮状病毒

1002: [FJOI2007]轮状病毒

Description

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

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

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

Input

  第一行有1个正整数n

Output

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

Sample Input

3

Sample Output

16
  用高精度自然不用说。
  据说物竞的同学都会基尔霍夫矩阵,他们说很容易得到:f[i]=f[i-1]*3-f[i-2]+2
  我们当然不会证,但不代表别人不会证:VFK神犇
  但是,这当然不是唯一的方法。
  法2:mcfx说,这不是组合数么-->就是组合数 这是O(n^2)的。
  法3: 有位神犇打表,发现分奇偶后是斐波那契数与平方-->斐波那契

  看来这种题也能有多种做法啊。

  高精度模板如下(+、-、*):

 1 const int BASE=100000000;
 2 struct NUM {int aa[100], len;};
 3 NUM plu(struct NUM x,int k) {
 4     x.aa[1]+=k;
 5     for( int j = 1; x.aa[j]>=BASE; j++ ) x.aa[j]%=BASE, x.aa[j+1]++;
 6     return x;
 7 }
 8 NUM mul(struct NUM x,int k) {
 9     for( int i = 1; i <= x.len; i++ ) x.aa[i]*=k;
10     for( int i = 1; i <= x.len; i++ ) {
11         x.aa[i+1]+=x.aa[i]/BASE;
12         x.aa[i]%=BASE;
13     }
14     if(x.aa[x.len+1]) x.len++;
15     return x;
16 }
17 NUM sub(struct NUM x,struct NUM y) {
18     for( int i = 1; i <= x.len; i++ ) {
19         x.aa[i]-=y.aa[i];
20         if(x.aa[i]<0) x.aa[i]+=BASE, x.aa[i+1]--;
21     }
22     while(x.aa[x.len]==0) x.len--;
23     return x;
24 }

  但是,如果我这样就把这道题给水了过去,连我都会过意不去。因为,这种题既然3种方法都是对的,那它们为什么等价?

  我早就说过了,我不会证。但列一下我该列的还是绰绰有余了。

  法1:f[i]=f[i-1]*3-f[i-2]+2          行列式递推

  法2:nk=1​​C(n+k1,k21)k/n​​ 组合计数

  法3:g[0]=2,g[1]=1,g[i]=g[i-1]+g[i-2](i>=2)-->这个跟下面那个挺像的

                 h[0]=1,h[1]=1,h[i]=h[i-1]+h[i-2](i>=2)-->这是斐波那契的递推式

      f[i]= g[i]*g[i]            若i为奇数

                        5*h[i-1]*h[i-1] 若i为偶数       打表

posted @ 2017-07-26 22:12  Doggu  阅读(299)  评论(0编辑  收藏  举报