BZOJ-1002 轮状病毒 高精度加减+Kirchhoff矩阵数定理+递推

1002: [FJOI2007]轮状病毒

Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 3543 Solved: 1953
[Submit][Status][Discuss]
Description
给定n(N<=100),编程计算有多少个不同的n轮状病毒。

Input
第一行有1个正整数n。

Output
将编程计算出的不同的n轮状病毒数输出

Sample Input
3

Sample Output
16

HINT

基尔霍夫矩阵Matrix-Tree定理,最小生成树数种类数,具体的参见此讲解:http://www.bubuko.com/infodetail-899543.html

对于本题的作用是用此方法模拟出前几组种类数,然后找递推式,加高精度答案即可

递推式为:F【n】=F【n-1】*3-F【n-2】+2

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;

struct data{
    int num[100];
};
data s0,s1,s2,s3;
int n;//s1表示f【n-2】,s2表示f【n-1】,s3记录答案,s0为常数2 

data add(data x,data y)
{
    int len=max(x.num[0],y.num[0]);
    data z;
    int jw=0;
    for (int i=1; i<=len; i++)
        {
            z.num[i]=(jw+x.num[i]+y.num[i])%10;
            jw=(jw+x.num[i]+y.num[i])/10;
        }
    if (jw!=0) z.num[++len]=jw;
    z.num[0]=len;
    return z;
}//高精度加法 

data sub(data x,data y)
{
    int len=max(x.num[0],y.num[0]);
    data z;
    for (int i=1; i<=len; i++)
        z.num[i]=x.num[i]-y.num[i];
    for (int i=1; i<=len; i++)
        if (z.num[i]<0) {z.num[i]+=10;z.num[i+1]--;}
    while (z.num[len]==0)
    {len--;}
    z.num[0]=len;
    return z;           
}//高精度减法 

int main()
{
    scanf("%d",&n);
    if (n==1) {printf("1"); return 0;}
    if (n==2) {printf("5"); return 0;}
    s1.num[1]=1;
    s2.num[1]=5;
    s1.num[0]=s2.num[0]=1;
    s0.num[0]=1;s0.num[1]=2;
    for (int i=3; i<=n; i++)
        {
            s3=add(sub(add(s2,add(s2,s2)),s1),s0);
            s1=s2;s2=s3;
        }
    for (int i=s3.num[0]; i>=1; i--)
        printf("%d",s3.num[i]);
    return 0;       
}
posted @ 2015-12-16 17:41  DaD3zZ  阅读(210)  评论(0编辑  收藏  举报