题目链接

题目给了你一个奇怪的图,让你求它的生成树个数。

开始写了一个矩阵树:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<bitset>
#include<cmath>
#define P puts("lala")
#define pc cerr<<"lala"<<endl
#define HH puts("")
#define pb push_back
#define pf push_front
#define fi first
#define se second
#define mkp make_pair
using namespace std;
inline void read(int &re)
{
char ch=getchar();int g=1;
while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
re=0;
while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
re*=g;
}
typedef long long ll;
inline void read(ll &re)
{
char ch=getchar();ll g=1;
while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
re=0;
while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+ch-48ll,ch=getchar();
re*=g;
} const int N=109; int n;
ll kir[N][N]; ll gauss()
{
ll ans=1;
for(int i=1;i<n;++i)
{
for(int j=i+1;j<n;++j)
{
while(kir[j][i])
{
ll t=kir[i][i]/kir[j][i];
for(int k=i;k<n;++k)
{
kir[i][k]=kir[i][k]-kir[j][k]*t;
swap(kir[i][k],kir[j][k]);
}
ans=-ans;
}
}
ans=ans*kir[i][i];
}
return ans;
} int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);freopen("1.out","w",stdout);
#endif
int i,j,opt,T;
read(n);
for(i=0;i<n;++i)
{
kir[i][i]++;kir[n][n]++;
kir[i][n]=-1;kir[n][i]=-1;
}
for(i=0;i<n;++i)
{
kir[i][i]++;kir[(i+1)%n][(i+1)%n]++;
kir[i][(i+1)%n]=-1;kir[(i+1)%n][i]=-1;
}
n++;
ll ans=gauss();
printf("%lld",abs(ans));
return 0;
}
/* */

发现答案会超过long long的范围,而用高精好像会T,于是花了几十分钟去推这个基尔霍夫矩阵行列式的递推式。

首先,我们把这个图的基尔霍夫矩阵最后一行最后一列消去,得到这样的矩阵A

|3 -1 0 ... ... 0 -1|

|-1 3 -1 0 ....0  0|

|0 -1 3 -1 0 ...  0|

|...      ...         ...|

|-1 0... ... ...-1 3 |

现在只需要求这个矩阵的行列式。

我们先假定n为奇数,偶数可以同样算出。

我们选择第一行消下去,得到的式子中有这么一项:

B:

|3 -1 0 ... ... 0  0|

|-1 3 -1 0 ....0  0|

|0 -1 3 -1 0 ...  0|

|...      ...         ...|

|0  0... ... ...-1 3 |

(注意它在(1,n)与(n,1)的元素与A不一样)

设长,宽为n的上面那个矩阵的行列式为f(n)

把矩阵A第一行消去后,得到3*f(n-1)与矩阵:(为了方便,以n=5为例画出来)

(+)

|-1 -1 0 0|

|0 3  -1 0|

|0 -1 3 -1|

|-1 0 -1 3|

(-)

|-1 3 -1 0|

|0 -1 3 -1|

|0  0 -1 3|

|-1 0 0 -1|

再对两个矩阵消去第一列,其中会得到两个三角矩阵(对角线上全是-1),直接算出来行列式为-1

得到det(A)=3*f(n-1)-2*f(n-2)-2

于是我们只需算出f(n)

对于f(n)同样的消两次,然后发现除了f(n-1),f(n-2),剩下的那个矩阵行列式为0(它有一整列都是0)

得到:f(n)=3*f(n-1)-f(n-2)

于是特判n=1,n=2,其余写高精递推即可

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<bitset>
#include<cmath>
#define P puts("lala")
#define pc cerr<<"lala"<<endl
#define HH puts("")
#define pb push_back
#define pf push_front
#define fi first
#define se second
#define mkp make_pair
using namespace std;
inline void read(int &re)
{
char ch=getchar();int g=1;
while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
re=0;
while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
re*=g;
}
typedef long long ll;
inline void read(ll &re)
{
char ch=getchar();ll g=1;
while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
re=0;
while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+ch-48ll,ch=getchar();
re*=g;
} const int N=109; int n; struct big
{
int len;
int s[100];
big() {clean();}
void clean()
{
memset(s,0,sizeof(s));len=0;
}
void operator = (int x)
{
for(;x;x/=10) s[len++]=x%10;
}
void print()
{
for(int i=len-1;i>=0;--i) printf("%d",s[i]);
putchar('\n');
}
}; big c;
big operator + (big a,big b)
{
int len=max(a.len,b.len);
c.clean();
c.len=len;
for(int i=0;i<len;++i) c.s[i]=a.s[i]+b.s[i];
for(int i=0;i<len;++i) c.s[i+1]+=c.s[i]/10,c.s[i]%=10;
if(c.s[len]) c.len++;
return c;
} big operator - (big a,big b)//a > b
{
c.clean();
for(int i=0;i<a.len;++i)
{
c.s[i]+=a.s[i]-b.s[i];
if(c.s[i]<0) c.s[i]+=10,a.s[i+1]--;
}
int len=a.len-1;
for(;!c.s[len];len--);
c.len=len+1;
return c;
} big operator * (big a,big b)
{
int len=a.len+b.len-1;
c.clean();
c.len=len;
for(int i=0;i<a.len;++i) for(int j=0;j<b.len;++j) c.s[i+j]+=a.s[i]*b.s[j];
for(int i=0;i<len;++i) c.s[i+1]+=c.s[i]/10,c.s[i]%=10;
if(c.s[len]) c.len++;
return c;
} big f[N]; int main()
{
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);freopen("1.out","w",stdout);
#endif
int i,j,opt,T;
read(n);
f[1]=3;f[2]=8; if(n==1) {printf("1");return 0;}
else if(n==2) {printf("5");return 0;} big three,two;
three=3;two=2; for(i=3;i<=n;++i) f[i]=three*f[i-1]-f[i-2]; big ans=(three*f[n-1])-(two*f[n-2])-two; ans.print();
return 0;
}
/* */

最新文章

  1. jQuery获取循环中的选中单选按钮radio的值
  2. DB2 SQL性能调优秘笈
  3. Linux命令练级初级
  4. DedeCMS时间格式
  5. D、GO、Rust 谁会在未来取代 C?为什么?——Go语言的定位非常好,Rust语言非常优秀,D语言也不错
  6. servlet其工作原理和例子证明
  7. linux系统安装iprouter
  8. HDU-5706
  9. luogu P5323 [BJOI2019]光线
  10. WPF中在MVVM模式下,后台绑定ListCollectionView事件触发问题
  11. 基于Rabbit实现的RPC
  12. Unity3D中Isometric Tilemap功能实践
  13. HZNU ACM一日游 2019.3.17 【2,4,6-三硝基甲苯(TNT)】
  14. 快速傅里叶变换(FFT)_转载
  15. gpg使用说明
  16. jdbc --- javabean
  17. PAT甲题题解-1044. Shopping in Mars (25)-水题
  18. python之旅:元类
  19. Matlab查看数值不用科学计数法显示
  20. Loj10153 二叉苹果树

热门文章

  1. 最新豆瓣top250爬虫案例代码分析[注释齐全]
  2. 构建数据湖上低延迟数据 Pipeline 的实践
  3. BZOJ3732 (Kruskal重构树)
  4. Redis 19 整合SpringBoot
  5. DS队列----银行单队列多窗口模拟
  6. HttpClient 在vivo内销浏览器的高并发实践优化
  7. ss 显示unix 域 的socket 缓冲区不正确
  8. 来开源吧!发布开源组件到 MavenCentral 仓库超详细攻略
  9. k8s数据持久化,pv和pvc
  10. 记一次 Sedona(GeoSpark) 空间计算优化