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

猜你喜欢

转载自www.cnblogs.com/ubospica/p/9808975.html