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

来源:互联网 发布:社招 算法题 编辑:程序博客网 时间:2024/05/18 18:02

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;       }
0 0
原创粉丝点击