我本以为这是个Matrix-tree裸题模板…没想到………………………………………………………………………………………………………………………………………………………………………………………………………………………………………..
1002: [FJOI2007]轮状病毒
Time Limit: 1 Sec Memory Limit: 162 MB
Submit: 3066 Solved: 1699
[Submit][Status][Discuss]
Description
给定n(N<=100),编程计算有多少个不同的n轮状病毒。
Input
第一行有1个正整数n。
Output
将编程计算出的不同的n轮状病毒数输出
Sample Input
3
Sample Output
16
HINT
Source
用了Gauss的Matrix-tree定理被卡精度了(/ω╲)
靠我还是去写递推吧QAQ(怪不得没人用定理做全都是递推)
证明一下递推式吧= =
首先我们在做裸的矩阵树定理的时候,这个图实际上是一个n+1个点的图,以中间那个为1号点,边上挨个编号.根据图的形状,可以看出他的行列式大概是一个很有规律的东西(注意n是输入的n行列式的实际大小是(n+1)*(n+1)):
det(C)=∣∣∣∣∣∣∣∣n−1−1⋮−1−13−1⋮−1−1−13⋮0−100⋮0⋯⋯⋯⋱⋯−1−1−1⋮−1−1−1−1⋮3∣∣∣∣∣∣∣∣
(大致看懂规律就行了…)
所以最后计算行列式的值的时候大概就是(这里的n是题目输入的n):
(P.S.如果你不信这个公式的话可以打个表看看= =)
f(n)=3∗f(n−1)−f(n−2)+2
想要证明?
我不会QAQ
用矩阵颓了半天颓出来个乱七八糟的东西( /ω╲)虽然结果对但是很显然没有递推关系…所以不拿出来了QAQ
请看VFK神犇>_<
VFK神犇
这是 被卡精度的代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAXN 110
#define eps 1e-9
using namespace std;
struct num
{
int a[10000];
int len;
}ans;
int A[MAXN][MAXN],D[MAXN][MAXN];
double C[MAXN][MAXN];
int n;
void gauss()
{
int now=1;
for (int i=1;i<=n+1;i++)
{
int x=now;
while (fabs(C[x][now])<eps&&x<=n+1) x++;
if (x==n+1)
{
puts("0");
return;
}
for (int j=1;j<=n+1;j++) swap(C[now][j],C[x][j]);
for (int j=now+1;j<=n+1;j++)
{
double tmp=C[j][now]/C[now][now];
for (int k=1;k<=n+1;k++)
C[j][k]-=C[now][k]*tmp;
}
now++;
}
ans.a[1]=1;ans.len=1;
for (int i=1;i<=n;i++)
{
long long T=(long long)(C[i][i]*1000000000000000);
num temp;
for (int i=1;i<=1000;i++) temp.a[i]=0;
temp.len=0;
while (T)
{
temp.a[++temp.len]=T%10;
T/=10;
}
num t;
for (int i=1;i<=1000;i++) t.a[i]=0;
t.len=0;
t.len=ans.len+temp.len;
for (int i=1;i<=ans.len;i++)
for (int j=1;j<=temp.len;j++)
{
t.a[i+j-1]+=ans.a[i]*temp.a[j];
if (t.a[i+j-1]>10)
{
t.a[i+j]+=t.a[i+j-1]/10;
t.a[i+j-1]%=10;
}
}
while (ans.a[ans.len]==0) ans.len--;
ans=t;
}
while (ans.a[ans.len]==0) ans.len--;
for (int i=ans.len;i>1500;i--) printf("%d",ans.a[i]);
}
int main()
{
freopen("virus.in","r",stdin);
scanf("%d",&n);
for (int i=2;i<=n+1;i++) ++A[i][1],++A[1][i],++D[1][1],++D[i][i];
for (int i=2;i<=n;i++) ++A[i][i+1],++A[i+1][i],++D[i+1][i+1],++D[i][i];
++A[n+1][2];++A[2][n+1];++D[2][2];++D[n+1][n+1];
for (int i=1;i<=n+1;i++)
for (int j=1;j<=n+1;j++)
C[i][j]=D[i][j]-A[i][j];
gauss();
}
这是递推Python水过代码
懒得高精只好Python
n=(int)(input())
a=5
b=1
if n<=2:
if n==1:
print(b)
else:
print(a)
else:
for i in range(3,n+1,1):
c=3*a-b+2
b=a
a=c
print(c)