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;
}

posted @ 2018-10-18 10:19  Ubospica  阅读(99)  评论(0编辑  收藏  举报