[BZOJ1002][FJOI2007]轮状病毒

询问生成树个数,一眼矩阵树定理...但是高消会爆精度,long double都存不下。不取模的计数题都是耍流氓! 所以,用Python打表就行了正解是递推打表找规律。其实可以用矩阵树直接推行列式的,但是我不会,回头再想一下吧.

矩阵树定理总结请看这里
50分爆精度代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <cstdio>
#include <cmath>
#include <algorithm>

using std::swap;
using std::fabs;

const int maxn=105;
const double eps=1e-6;

long double K[maxn][maxn];

inline void add(int u,int v)
{
++K[u][u];++K[v][v];
--K[u][v];--K[v][u];
}

inline long double determinant(long double (*A)[maxn],int n)
{
int s=1;
for (int i=1,c=1,j;i<=n;++i)
{
for (j=c;j<=n && fabs(A[j][i])<eps;++j);
if (j==n+1) continue;
s=-s;
for (int k=1;k<=n;++k) swap(A[c][k],A[j][k]);
for (int j=c+1;j<=n;++j)
if (fabs(A[j][i])>eps)
{
long double t=A[j][i]/A[c][i];
for (int k=i;k<=n;++k)
A[j][k]-=A[c][k]*t;
}
++c;
}
long double ans=s;
for (int i=1;i<=n;++i)
ans*=A[i][i];
return fabs(ans);//这里要取绝对值
}

int main()
{
int n;
scanf("%d",&n);++n;
if (n==1) return puts("1")&0;
for (int i=3;i<=n;++i) add(i,i-1);
for (int i=2;i<=n;++i) add(i,1);
if (n>2) add(2,n);
printf("%.0LF",determinant(K,n-1));
}