BZOJ 1002 轮状病毒 生成树计数(行列式递推)

来源:互联网 发布:mac能用淘宝千牛吗 编辑:程序博客网 时间:2024/05/17 09:31
题意:如图所示的n轮环形图.只保留其n-1条边,并且每两点都要有唯一路径存在.
n<=100 问n保留边的方案数?

给出图求其生成树个数,先建下Kirchhoff Matrix,求出其n-1阶行列式的值就好了.

然而这题求行列式的时候精度好像炸了,把行列式展开后有递推关系 参考链接:点击打开链接 点击打开链接

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=2e3+20;int n;struct node{int a[N],l;node(){memset(a,0,sizeof(a));l=1;}friend node operator *(int x,node &y){node ret;ret.l=y.l+1;for(int i=1;i<=y.l;i++){ret.a[i]+=y.a[i]*x;ret.a[i+1]+=ret.a[i]/10;ret.a[i]%=10;}if(ret.a[ret.l]==0) ret.l--;return ret;} friend inline node operator -(node x,node y)    {        node z; z.l = max(x.l,y.l);        for (int i = 1;i <= z.l;++i)        {            z.a[i] = x.a[i]-y.a[i];            while (z.a[i] < 0)                z.a[i] += 10,x.a[i+1]--;        }        while (z.l > 1&&z.a[z.l] == 0)z.l--;        return z;    }    friend inline node operator +(node &x,int y)    {        node ret = x;        ret.a[1] += y;        for (int i = 1;i <= ret.l;++i)        {            if (ret.a[i] >= 10)                ret.a[i]-=10,ret.a[i+1]++;            else break;        }        if (ret.a[ret.l+1]) ret.l++;        return ret;    }    inline void print()    {        for (int i = l;i >= 1;--i)            printf("%d",this->a[i]);    }}g[N],ans;void solve(){scanf("%d",&n);g[1]=g[1]+3;g[2]=g[2]+8;if(n<=2){g[n].print();return;}for(int i=3;i<=n;i++)g[i]=3*g[i-1]-g[i-2];ans=3*g[n-1]-2*g[n-2];ans=ans+(-2);ans.print();}int main(){solve();return 0;}