【题意分析】

  给你一张特殊的,被称为“轮状基”的无向图,求其生成树个数。

【解题思路】

引理:

  基尔霍夫矩阵

基尔霍夫矩阵=度数矩阵-邻接矩阵(邻接矩阵权=两点连边数)

  Matrix-Tree定理

对于任意一个无向图,其生成树个数为其基尔霍夫矩阵的任意一个余子式的行列式值。

算法一:

  直接暴力构图,用Matrix-Tree定理算出生成树个数,复杂度O(n3),理论可过,但考虑到高精度。。

  附上一个算矩阵行列式的小公举工具。

算法二:

  听说这个图很特殊,那一定有一些特殊性质?

  先写出这个基尔霍夫矩阵的一般形态:

  答案就是他的任意一个代数余子式的行列式值,为了最简化问题,我们可以去掉第一行第一列:

  那么只要求这个矩阵的行列式值就可以了。

  我们先初等变换一下:

  这样答案就等于这个矩阵的行列式值前面加个符号,即乘上(-1)n-1

  寻找这个矩阵行列式计算的规律,发现对倒数第二行进行高斯消元:

  可得递推式组:

  • Fi=Gi-1+3*Fi-1
  • Gi=-Fi-1

  整理后即Fi=3*Fi-1-Fi-2(边界F1=-1,F2=-3)

  于是可以矩阵可以变换为这种形式:

  同理,对倒数第一行进行高斯消元,矩阵最终变为:

  其行列式为:(-1)n-2*f*(i-g*h/f)=(-1)n-2*(f*i-g*h)

  则原行列式值为:(-1)2n-3*(f*i-g*h)=g*h-f*i

  带入各函数,结合关于行列式的FH定理,展开得:Hn+Fn-1-2

  设原式=Rn,可得递推式:Rn=3*Rn-1-Rn-2+2(R1=2,R2=5)

  这就是答案递推式了,复杂度O(n)。

  恩,更详尽的证明,让vfk带你飞!

算法三:

  打表找规律!(听说这就是我当初把这题当成高精度练习题的理由)

  设Fi=3*Fi-2-Fi-4,则当i为奇数时,ansi=Fi2,当i为偶数时,ansi=5*Fi2

  复杂度O(n)

【参考程序】

//听说我写这题时我还没有听说过一个叫做Py的东西。。QAQ

//这个板子还有可能是错的。。QAQ

 #include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stack>
#define REP(I,start,end) for(int I=start;I<=end;I++)
#define PER(I,start,end) for(int I=start;I>=end;I--)
using namespace std;
long long digiter=100000000ll;
inline void init(long long initer)
{
digiter=initer;
}
struct bigNumber
{
int len;
long long num[];
inline void operator =(long long T)
{
memset(num,,sizeof(num));
len=;
while(T)
{
num[++len]=T%digiter;
T/=digiter;
}
}
bool positive()
{
return len&&num[len]>;
}
bool odd()
{
return num[]&;
}
inline bool operator ==(const bigNumber& T)const
{
if(len!=T.len)
return false;
REP(i,,len)
if(num[i]!=T.num[i])
return false;
return true;
}
inline bool operator >(const bigNumber& T)const
{
if(len<T.len)
return false;
if(len>T.len)
return true;
PER(i,len,)
{
if(num[i]<T.num[i])
return false;
if(num[i]>T.num[i])
return true;
}
return false;
}
inline bool operator >=(const bigNumber& T)const
{
if(len<T.len)
return false;
if(len>T.len)
return true;
PER(i,len,)
{
if(num[i]<T.num[i])
return false;
if(num[i]>T.num[i])
return true;
}
return true;
}
inline bool operator <(const bigNumber& T)const
{
if(len>T.len)
return false;
if(len<T.len)
return true;
PER(i,len,)
{
if(num[i]>T.num[i])
return false;
if(num[i]<T.num[i])
return true;
}
return false;
}
inline bool operator <=(const bigNumber& T)const
{
if(len>T.len)
return false;
if(len<T.len)
return true;
PER(i,len,)
{
if(num[i]>T.num[i])
return false;
if(num[i]<T.num[i])
return true;
}
return true;
}
inline void operator +=(const long long TT)
{
long long T=TT;
int i=;
while(T)
{
num[i]+=T%digiter;
T/=digiter;
i++;
}
REP(i,,len)
{
num[i+]+=num[i]/digiter;
num[i]%=digiter;
}
while(num[len+])
len++;
}
inline void operator -=(const long long TT)
{
long long T=TT;
int i=;
while(T)
{
num[i]-=T%digiter;
T/=digiter;
i++;
}
REP(i,,len)
while(num[i]<0ll)
{
num[i+]--;
num[i]+=digiter;
}
while(len&&num[len]==0ll)
len--;
}
inline void operator *=(const long long T)
{
REP(i,,len)
num[i]*=T;
REP(i,,len)
{
num[i+]+=num[i]/digiter;
num[i]%=digiter;
}
while(num[len+])
{
len++;
num[len+]+=num[len]/digiter;
num[len]%=digiter;
}
}
inline void operator /=(const long long T)
{
long long rest=0ll;
PER(i,len,)
{
rest=rest*digiter+num[i];
num[i]=rest/T;
rest%=T;
}
while(len&&num[len]==0ll)
len--;
}
}f[],three;
inline bigNumber operator +(const bigNumber A,const bigNumber B)
{
bigNumber C;
memset(C.num,,sizeof(C.num));
C.len=max(A.len,B.len);
REP(i,,C.len)
C.num[i]=A.num[i]+B.num[i];
REP(i,,C.len)
{
C.num[i+]+=C.num[i]/digiter;
C.num[i]%=digiter;
}
while(C.num[C.len+])
{
C.len++;
C.num[C.len+]+=C.num[C.len]/digiter;
C.num[C.len]%=digiter;
}
return C;
}
inline bigNumber operator -(const bigNumber A,const bigNumber B)
{
bigNumber C;
memset(C.num,,sizeof(C.num));
C.len=max(A.len,B.len);
REP(i,,C.len)
C.num[i]=A.num[i]-B.num[i];
REP(i,,C.len)
while(C.num[i]<)
{
C.num[i+]--;
C.num[i]+=digiter;
}
while(C.len&&C.num[C.len]==)
C.len--;
return C;
}
inline bigNumber operator *(const bigNumber A,const bigNumber B)
{
bigNumber C;
memset(C.num,,sizeof(C.num));
C.len=A.len+B.len-;
REP(i,,A.len)
REP(j,,B.len)
{
C.num[i+j-]+=A.num[i]*B.num[j];
C.num[i+j]+=C.num[i+j-]/digiter;
C.num[i+j-]%=digiter;
}
while(C.num[C.len+])
{
C.len++;
C.num[C.len+]+=C.num[C.len]/digiter;
C.num[C.len]%=digiter;
}
while(C.num[C.len]==)
C.len--;
return C;
}
inline long long operator %(const bigNumber A,const long long B)
{
long long T=;
PER(i,A.len,)
T=(T*digiter+A.num[i])%B;
return T;
}
inline bigNumber gcd(const bigNumber AA,const bigNumber BB)
{
bigNumber C,A=AA,B=BB;
while(B.positive())
{
C=A;
while(C>=B)
C=C-B;
A=B;
B=C;
}
return A;
}
inline bigNumber sqr(const bigNumber T)
{
return T*T;
}
inline bigNumber power(const bigNumber A,const int B)
{
stack<bool> isODD;
while(!isODD.empty())
isODD.pop();
int tmp=B;
while(tmp)
{
isODD.push(tmp&);
tmp>>=;
}
bigNumber C;
C=1ll;
while(!isODD.empty())
{
C=sqr(C);
if(isODD.top())
C=C*A;
isODD.pop();
}
return C;
}
inline bigNumber fact(int n)
{
bigNumber ans;
ans=1ll;
REP(i,,n)
ans*=i;
return ans;
}
inline bigNumber max(const bigNumber A,const bigNumber B)
{
if(A>B)
return A;
return B;
}
inline bigNumber min(const bigNumber A,const bigNumber B)
{
if(A<B)
return A;
return B;
}
inline void scan(bigNumber& T)
{
memset(T.num,,sizeof(T.num));
if(digiter==10ll)
{
T.len=;
char ch=getchar();
while(ch<''||ch>'')
ch=getchar();
while(ch>=''&&ch<='')
{
T.num[++T.len]=ch-'';
ch=getchar();
}
REP(i,,T.len>>)
swap(T.num[i],T.num[T.len-i+]);
}
else
{
string st;
cin>>st;
T.len=;
long long tmp=1ll;
PER(i,st.length()-,)
{
T.num[T.len]+=(st[i]-'')*tmp;
tmp*=10ll;
if(tmp==digiter)
{
T.len++;
tmp=1ll;
}
}
if(tmp==1ll)
T.len--;
}
}
inline void print(const bigNumber T)
{
if(T.len==)
{
putchar('');
return;
}
if(digiter==10ll)
PER(i,T.len,)
putchar(char(T.num[i])+'');
else
{
printf("%lld",T.num[T.len]);
PER(i,T.len-,)
{
long long tmp=digiter/10ll;
while(tmp)
{
printf("%lld",T.num[i]/tmp%10ll);
tmp/=10ll;
}
}
}
}
int n;
int main()
{
scanf("%d",&n);
f[]=1ll;
f[]=1ll;
f[]=4ll;
f[]=3ll;
three=3ll;
REP(i,,n)
f[i]=f[i-]*three-f[i-];
f[n]=sqr(f[n]);
if(~n&)
f[n]*=5ll;
print(f[n]);
return ;
}

  和Py比较一下。。

 if __name__=="__main__":
n,last,ans=input(),1,5
if n<2:
print 2
else:
for i in xrange(n-2):
ans,last=3*ans-last+2,ans
print ans

QAQ

最新文章

  1. spring整合struts2
  2. KMP模式匹配练习题
  3. 理解模数转换器的噪声、ENOB和有效分辨率
  4. ABAP版连连看
  5. 时间序列数据库选型——本质是列存储,B-tree索引,抑或是搜索引擎中的倒排索引
  6. Java BigInteger(大数,ACM比赛专用)
  7. 并发编程之二:wait、notify、notifyAll的使用方法
  8. NUnit Test Adapter----单元测试需要安装这个插件
  9. 基于Qt的开源音乐播放器(CZPlayer)
  10. MapReduce编程系列 — 1:计算单词
  11. 【POJ】2278 DNA Sequence
  12. poj1305:概念水题
  13. React-nwb的使用
  14. bootstarp栅格系统
  15. UVA - 10129Play on Words(欧拉路)
  16. c语言单链表,冒泡排序
  17. 【模式识别】Boosting
  18. NUMBER_GET_NEXT 获取编号 遇到关于按年度编号的问题
  19. cookie大小
  20. DAY5-小别-2018-1-15

热门文章

  1. 39th 迷迷糊糊 二豆玩不转了
  2. koa2 的处理请求体koa-bodyparser koa-router 的中间件的学习
  3. Android开发 VideoView视频播放详解
  4. 9、Python 连接 PostgreSQL数据库 -- psycopg2
  5. Excel处理
  6. mysql的数据导出方法2
  7. k8s集群搭建之一:基础环境
  8. Springboot开篇
  9. Zend Studio出现 Some characters cannot be mapped using &quot;GBK&quot; character encoding 错误
  10. java的collection&amp;&amp;map集合总结