bzoj1002-[FJOI2007]轮状病毒
基尔霍夫矩阵求最小生成树计数.
之后打表发现
\[f_1 = 1, f_2 = 5
\]
\[f_i = 3 * f_{i-1} - f_{i-2} + 2 (i \ge 3)
\]
证明见vfk大爷的博客.
高精度模拟即可.
另外,注意高精度输出时前面要补0,详见代码.
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
using namespace std;
#define rep(i,l,r) for(register int i=(l);i<=(r);++i)
#define repdo(i,l,r) for(register int i=(l);i>=(r);--i)
#define il inline
typedef double db;
typedef long long ll;
//---------------------------------------
const int nsz=105;
int n;
const int nbl=100,bsz=10000;
struct tbig{
int val[nbl];
void set(int v){
val[0]=0;
for(;v;v/=bsz){
val[++val[0]]=v%bsz;
}
}
void pr(){
printf("%d",val[val[0]]);
repdo(i,val[0]-1,1)printf("%04d",val[i]); //important
}
}dp[nsz],v2;
tbig sub(tbig a,tbig b){//a-b+2
a.val[1]+=2;
rep(i,1,a.val[0]){
if(a.val[i]<bsz)break;
a.val[i]-=bsz,a.val[i+1]+=1;
}
rep(i,1,a.val[0]){
a.val[i]-=b.val[i];
if(a.val[i]<0)a.val[i]+=bsz,--a.val[i+1];
}
if(a.val[a.val[0]]==0)--a.val[0];
return a;
}
tbig mul(tbig a,int b){//a*b
rep(i,1,a.val[0]){
a.val[i]*=b;
}
rep(i,1,a.val[0]){
if(a.val[i]>bsz)a.val[i+1]+=a.val[i]/bsz,a.val[i]%=bsz;
}
while(a.val[a.val[0]+1])++a.val[0];
return a;
}
int main(){
// ios::sync_with_stdio(0),cin.tie(0);
cin>>n;
v2.set(-2);
dp[1].set(1),dp[2].set(5);
rep(i,3,n){
dp[i]=sub(mul(dp[i-1],3),dp[i-2]);
}
dp[n].pr();
putchar('\n');
return 0;
}