1002: [FJOI2007]轮状病毒
Posted acm1ruoji
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1002: [FJOI2007]轮状病毒相关的知识,希望对你有一定的参考价值。
题意:就是给出n,表示有n+1个点通过n条边相连。求一共有多少种连法!总的来说就是求生成树的个数有多少种
其实说了一大堆就是证明了f[i]=3f[i-1]-f[i-2]+2。这个就是本题的递推式
而这个怎么来的?大佬的证明说明了一个基尔霍夫矩阵的任一余子式的行列式的值就是该图的生成树的个数
所以我们就可以通过对余子式做代数余子式的展开求行列式的方法,就可以推出上面那个公式,不会推就记住好了(反正我觉得我就算现在会推过几天就忘了emmm)
本题虽然最大数据只有100,但是还是顶不住爆ll,所以要写个高精度加法跟减法,那个乘法相当于加三次(我不想敲高精度乘法,主要是不太会)
#include <set> #include <map> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <sstream> #include <algorithm> #include <vector> #include <stack> #include <queue> #include <iostream> #include <functional> using namespace std; #define ll long long #define fi first #define se second #define re register #define pb push_back void read(int &a) { a=0; int d=1; char ch; while(ch=getchar(),ch>‘9‘||ch<‘0‘) if(ch==‘-‘) d=-1; a=ch-‘0‘; while(ch=getchar(),ch>=‘0‘&&ch<=‘9‘) a=a*10+ch-‘0‘; a*=d; } void write(int x) { if(x<0) putchar(45),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); } string f[105]; string add(string st1,string st2) { string str; int d=0; int len1=st1.length(); int len2=st2.length(); if(len1>len2) for(re int i=0;i<len1-len2;i++) st2=‘0‘+st2; else for(re int i=0;i<len2-len1;i++) st1=‘0‘+st1; for(re int i=st1.size()-1;i>=0;i--) { int a,b; a=st1[i]-‘0‘; b=st2[i]-‘0‘; a=a+b+d; d=a/10; str=char(a%10+‘0‘)+str; } if(d!=0) str=char(d+‘0‘)+str; return str; } string solve(int x) { string s=""; do { s.pb(x%10); x/=10; }while(x); reverse(s.begin(),s.end()); return s; } string sub(string st1,string st2) { string tem; int d=0; bool f=true; int len1=st1.length(); int len2=st2.length(); if(len1<len2||(len1==len2&&st1<st2)) { string t=st1; st1=st2; st2=t; int tt=len1; len1=len2; len2=tt; f=false; } else if(len1==len2&&st1==st2) { tem=‘0‘; return tem; } for(re int i=1;i<=len1-len2;i++) st2=‘0‘+st2; for(re int i=len1-1;i>=0;i--) { int t=(st1[i]-‘0‘)-(st2[i]-‘0‘)-d; if(t<0) { t+=10; d=1; } else d=0; tem=char(t+‘0‘)+tem; } if(tem.size()==1) { if(!f) tem=‘-‘+tem; return tem; } while(1) { if(tem[0]==‘0‘) tem.erase(0,1); else break; } if(!f) tem=‘-‘+tem; return tem; } int main() { int n;read(n); string st1,st2; f[1]="1",f[2]="5"; st1=solve(n);st2=solve((n+1)*n); for(re int i=3;i<=n;i++) { for(re int j=1;j<=3;j++) f[i]=add(f[i],f[i-1]); f[i]=add(f[i],"2"); f[i]=sub(f[i],f[i-2]); } cout<<f[n]<<endl; return 0; }
以上是关于1002: [FJOI2007]轮状病毒的主要内容,如果未能解决你的问题,请参考以下文章