题目链接

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

开始写了一个矩阵树:

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<vector>
  6. #include<algorithm>
  7. #include<queue>
  8. #include<bitset>
  9. #include<cmath>
  10. #define P puts("lala")
  11. #define pc cerr<<"lala"<<endl
  12. #define HH puts("")
  13. #define pb push_back
  14. #define pf push_front
  15. #define fi first
  16. #define se second
  17. #define mkp make_pair
  18. using namespace std;
  19. inline void read(int &re)
  20. {
  21. char ch=getchar();int g=1;
  22. while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
  23. re=0;
  24. while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
  25. re*=g;
  26. }
  27. typedef long long ll;
  28. inline void read(ll &re)
  29. {
  30. char ch=getchar();ll g=1;
  31. while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
  32. re=0;
  33. while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+ch-48ll,ch=getchar();
  34. re*=g;
  35. }
  36.  
  37. const int N=109;
  38.  
  39. int n;
  40. ll kir[N][N];
  41.  
  42. ll gauss()
  43. {
  44. ll ans=1;
  45. for(int i=1;i<n;++i)
  46. {
  47. for(int j=i+1;j<n;++j)
  48. {
  49. while(kir[j][i])
  50. {
  51. ll t=kir[i][i]/kir[j][i];
  52. for(int k=i;k<n;++k)
  53. {
  54. kir[i][k]=kir[i][k]-kir[j][k]*t;
  55. swap(kir[i][k],kir[j][k]);
  56. }
  57. ans=-ans;
  58. }
  59. }
  60. ans=ans*kir[i][i];
  61. }
  62. return ans;
  63. }
  64.  
  65. int main()
  66. {
  67. #ifndef ONLINE_JUDGE
  68. freopen("1.in","r",stdin);freopen("1.out","w",stdout);
  69. #endif
  70. int i,j,opt,T;
  71. read(n);
  72. for(i=0;i<n;++i)
  73. {
  74. kir[i][i]++;kir[n][n]++;
  75. kir[i][n]=-1;kir[n][i]=-1;
  76. }
  77. for(i=0;i<n;++i)
  78. {
  79. kir[i][i]++;kir[(i+1)%n][(i+1)%n]++;
  80. kir[i][(i+1)%n]=-1;kir[(i+1)%n][i]=-1;
  81. }
  82. n++;
  83. ll ans=gauss();
  84. printf("%lld",abs(ans));
  85. return 0;
  86. }
  87. /*
  88.  
  89. */

发现答案会超过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,其余写高精递推即可

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cstring>
  4. #include<iostream>
  5. #include<vector>
  6. #include<algorithm>
  7. #include<queue>
  8. #include<bitset>
  9. #include<cmath>
  10. #define P puts("lala")
  11. #define pc cerr<<"lala"<<endl
  12. #define HH puts("")
  13. #define pb push_back
  14. #define pf push_front
  15. #define fi first
  16. #define se second
  17. #define mkp make_pair
  18. using namespace std;
  19. inline void read(int &re)
  20. {
  21. char ch=getchar();int g=1;
  22. while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
  23. re=0;
  24. while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+(ch^48),ch=getchar();
  25. re*=g;
  26. }
  27. typedef long long ll;
  28. inline void read(ll &re)
  29. {
  30. char ch=getchar();ll g=1;
  31. while(ch<'0'||ch>'9') {if(ch=='-')g=-1;ch=getchar();}
  32. re=0;
  33. while(ch<='9'&&ch>='0') re=(re<<1)+(re<<3)+ch-48ll,ch=getchar();
  34. re*=g;
  35. }
  36.  
  37. const int N=109;
  38.  
  39. int n;
  40.  
  41. struct big
  42. {
  43. int len;
  44. int s[100];
  45. big() {clean();}
  46. void clean()
  47. {
  48. memset(s,0,sizeof(s));len=0;
  49. }
  50. void operator = (int x)
  51. {
  52. for(;x;x/=10) s[len++]=x%10;
  53. }
  54. void print()
  55. {
  56. for(int i=len-1;i>=0;--i) printf("%d",s[i]);
  57. putchar('\n');
  58. }
  59. };
  60.  
  61. big c;
  62. big operator + (big a,big b)
  63. {
  64. int len=max(a.len,b.len);
  65. c.clean();
  66. c.len=len;
  67. for(int i=0;i<len;++i) c.s[i]=a.s[i]+b.s[i];
  68. for(int i=0;i<len;++i) c.s[i+1]+=c.s[i]/10,c.s[i]%=10;
  69. if(c.s[len]) c.len++;
  70. return c;
  71. }
  72.  
  73. big operator - (big a,big b)//a > b
  74. {
  75. c.clean();
  76. for(int i=0;i<a.len;++i)
  77. {
  78. c.s[i]+=a.s[i]-b.s[i];
  79. if(c.s[i]<0) c.s[i]+=10,a.s[i+1]--;
  80. }
  81. int len=a.len-1;
  82. for(;!c.s[len];len--);
  83. c.len=len+1;
  84. return c;
  85. }
  86.  
  87. big operator * (big a,big b)
  88. {
  89. int len=a.len+b.len-1;
  90. c.clean();
  91. c.len=len;
  92. 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];
  93. for(int i=0;i<len;++i) c.s[i+1]+=c.s[i]/10,c.s[i]%=10;
  94. if(c.s[len]) c.len++;
  95. return c;
  96. }
  97.  
  98. big f[N];
  99.  
  100. int main()
  101. {
  102. #ifndef ONLINE_JUDGE
  103. freopen("1.in","r",stdin);freopen("1.out","w",stdout);
  104. #endif
  105. int i,j,opt,T;
  106. read(n);
  107. f[1]=3;f[2]=8;
  108.  
  109. if(n==1) {printf("1");return 0;}
  110. else if(n==2) {printf("5");return 0;}
  111.  
  112. big three,two;
  113. three=3;two=2;
  114.  
  115. for(i=3;i<=n;++i) f[i]=three*f[i-1]-f[i-2];
  116.  
  117. big ans=(three*f[n-1])-(two*f[n-2])-two;
  118.  
  119. ans.print();
  120. return 0;
  121. }
  122. /*
  123.  
  124. */

FJOI2007轮状病毒 行列式递推详细证明的更多相关文章

  1. BZOJ1002 [FJOI2007] 轮状病毒 【递推】

    题目分析: 推基尔霍夫矩阵后可以发现递推式 代码: n = input() f0 = 1 f1 = 5 f3 = 0 if n == 1: print f0 elif n == 2: print f1 ...

  2. [bzoj1002][FJOI2007]轮状病毒_递推_高精度

    轮状病毒 bzoj-1002 FJOI-2007 Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2 ...

  3. BZOJ_1002_[FJOI2007]_轮状病毒_(递推+高精)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1002 )*&*(^&*^&*^**()*) 1002: [FJOI20 ...

  4. BZOJ 1002 FJOI2007 轮状病毒 递推+高精度

    题目大意:轮状病毒基定义如图.求有多少n轮状病毒 这个递推实在是不会--所以我选择了打表找规律 首先执行下面程序 #include<cstdio> #include<cstring& ...

  5. 【BZOJ】1002: [FJOI2007]轮状病毒 递推+高精度

    1002: [FJOI2007]轮状病毒 Description 给定n(N<=100),编程计算有多少个不同的n轮状病毒. Input 第一行有1个正整数n. Output 将编程计算出的不同 ...

  6. BZOJ-1002 轮状病毒 高精度加减+Kirchhoff矩阵数定理+递推

    1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 3543 Solved: 1953 [Submit][Statu ...

  7. 51nod 1126 求递推序列的第N项 思路:递推模拟,求循环节。详细注释

    题目: 看起来比较难,范围10^9 O(n)都过不了,但是仅仅是看起来.(虽然我WA了7次 TLE了3次,被自己蠢哭) 我们观察到 0 <= f[i] <= 6 就简单了,就像小学初中学的 ...

  8. P1759 通天之潜水(不详细,勿看)(动态规划递推,组合背包,洛谷)

    题目链接:点击进入 题目分析: 简单的组合背包模板题,但是递推的同时要刷新这种情况使用了哪些物品 ac代码: #include<bits/stdc++.h> using namespace ...

  9. 洛谷 P2144 [FJOI2007]轮状病毒

    P2144 [FJOI2007]轮状病毒 题目描述 轮状病毒有很多变种.许多轮状病毒都是由一个轮状基产生.一个\(n\)轮状基由圆环上\(n\)个不同的基原子和圆心的一个核原子构成.\(2\)个原子之 ...

随机推荐

  1. MySQL 启停过程了解一二

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. GreatSQL是MySQL的国产分支版本,使用上与MySQL一致. 前言 你知道MySQL启停都做了些什么吗? 启动的时 ...

  2. 万答#9,MySQL 中有哪些常用的日志

    欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 前 ...

  3. 数据结构与算法【Java】02---链表

    前言 数据 data 结构(structure)是一门 研究组织数据方式的学科,有了编程语言也就有了数据结构.学好数据结构才可以编写出更加漂亮,更加有效率的代码. 要学习好数据结构就要多多考虑如何将生 ...

  4. Pycharm5个非常有用的技巧

    PyCharm 是一款非常强大的编写 python 代码的工具.掌握一些小技巧能成倍的提升写代码的效率,本篇介绍几个经常使用的小技巧. 一.分屏展示 当你想同时看到多个文件的时候: 右击标签页: 选择 ...

  5. 事物的隔离性和MVCC

    事物的隔离性 mysql的服务端是支持多个客户端同时与之连接的,每个客户端可能还并发了好几个连接,所以mysql是需要同时处理很多事情的,每一件独立的事情就叫做事务.我们知道事务有一个叫隔离性的特性, ...

  6. Clickhouse基准测试实践

    1.概述 本篇博客将对MySQL.InfluxDB.Clickhouse在写入时间.聚合查询时间.磁盘使用等方面的性能指标来进行比较. 2.内容 比较的数据集,是使用的Clickhouse官网提供的6 ...

  7. 7个自定义定时任务并发送消息至邮箱或企业微信案例(crontab和at)

    前言 更好熟悉掌握at.crontab定时自定义任务用法. 实验at.crontab定时自定义任务运用场景案例. 作业.笔记需要. 定时计划任务相关命令及配置文件简要说明 at 工具 由包 at 提供 ...

  8. Html飞机大战(六):移动飞机

    好家伙,这篇移动主角   我们先来看看一个好东西, addEventListener() 方法 (他真的很好用)   我们直译一下,就叫他添加事件监听器方法   而可监听的对象就有很多啦 我们来了解一 ...

  9. 没有二十年功力,写不出Thread.sleep(0)这一行“看似无用”的代码!

    你好呀,我是喜提七天居家隔离的歪歪. 这篇文章要从一个奇怪的注释说起,就是下面这张图: 我们可以不用管具体的代码逻辑,只是单单看这个 for 循环. 在循环里面,专门有个变量 j,来记录当前循环次数. ...

  10. KingbaseES where 条件解析顺序

    概述 KingbaseES 对于where 条件的解析严格遵守"从左到右"的原则,因此,对于选择性比较强的条件,进行最先过滤是有利于性能的. 一.KingbaseES 1.条件顺序 ...