【fjoi2007】轮状病毒-递推+高精度 代码 连接

有一个连通图,中心有一个点连向外面的N个顶点,外围的每个顶点与相邻两点有连边。求最小生成树个数。

基尔霍夫矩阵。

根据数据范围,显然可以用基尔霍夫矩阵搞定。当然我用的是递推,a[n]=3*a[n-1]-a[n-2]+2.递推求解即可。注意写高精度。

代码

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
53
54
55

#include<cstring>
#define CK 10000
using namespace std;
int n;
class {
public:
int len;
int s[1010];
void clean(void){memset(s,0,sizeof(s)); len=1;}
void write(void){printf("%d",s[len-1]);
for (int i=len-2;i>=0;i--) printf("%.4d",s[i]);}
};
Marvolo a,b,c;
inline Marvolo operator *(int x,Marvolo y){
int i=0;
for (i=0;i<=y.len-1;i++) y.s[i]*=3;
for (i=0;i<y.len||y.s[i]>0;i++){
y.s[i+1]+=y.s[i]/CK; y.s[i]%=CK;
}
y.len=i;
return y;
}
inline Marvolo operator -(Marvolo x,Marvolo y){
int i=0;
for (i=0;i<y.len;i++) x.s[i]-=y.s[i];
for (i=x.len-1;i>=1;i--) x.s[i]-=1,x.s[i-1]+=CK;
for (i=0;i<x.len||x.s[i]>0;i++){
x.s[i+1]+=x.s[i]/CK; x.s[i]%=CK;
}
x.len=i;
return x;
}
inline Marvolo operator +(Marvolo x,int y){
int i=0;
x.s[0]+=2;
for (i=0;i<x.len||x.s[i]>0;i++){
x.s[i+1]+=x.s[i]/CK; x.s[i]%=CK;
}
x.len=i;
return x;
}
int main(){
a.len=1; a.s[0]=1;
b.len=1; b.s[0]=5;
scanf("%d",&n);
if (n==1) {printf("1n"); goto END;}
else if (n==2) {printf("5n"); goto END;}
for (int i=3;i<=n;i++){
c=3*b; c=c-a; c=c+2; a=b; b=c;
}
b.write();
END:
return 0;
}

连接

COGS
BZOJ