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;
}
——It's a lonely path. Don't make it any lonelier than it has to be.