FJOI2007轮状病毒 行列式递推详细证明
题目给了你一个奇怪的图,让你求它的生成树个数。
开始写了一个矩阵树:
- #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;
- }
- /*
- */
FJOI2007轮状病毒 行列式递推详细证明的更多相关文章
- BZOJ1002 [FJOI2007] 轮状病毒 【递推】
题目分析: 推基尔霍夫矩阵后可以发现递推式 代码: n = input() f0 = 1 f1 = 5 f3 = 0 if n == 1: print f0 elif n == 2: print f1 ...
- [bzoj1002][FJOI2007]轮状病毒_递推_高精度
轮状病毒 bzoj-1002 FJOI-2007 Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的.一个N轮状基由圆环上N个不同的基原子和圆心处一个核原子构成的,2 ...
- BZOJ_1002_[FJOI2007]_轮状病毒_(递推+高精)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1002 )*&*(^&*^&*^**()*) 1002: [FJOI20 ...
- BZOJ 1002 FJOI2007 轮状病毒 递推+高精度
题目大意:轮状病毒基定义如图.求有多少n轮状病毒 这个递推实在是不会--所以我选择了打表找规律 首先执行下面程序 #include<cstdio> #include<cstring& ...
- 【BZOJ】1002: [FJOI2007]轮状病毒 递推+高精度
1002: [FJOI2007]轮状病毒 Description 给定n(N<=100),编程计算有多少个不同的n轮状病毒. Input 第一行有1个正整数n. Output 将编程计算出的不同 ...
- BZOJ-1002 轮状病毒 高精度加减+Kirchhoff矩阵数定理+递推
1002: [FJOI2007]轮状病毒 Time Limit: 1 Sec Memory Limit: 162 MB Submit: 3543 Solved: 1953 [Submit][Statu ...
- 51nod 1126 求递推序列的第N项 思路:递推模拟,求循环节。详细注释
题目: 看起来比较难,范围10^9 O(n)都过不了,但是仅仅是看起来.(虽然我WA了7次 TLE了3次,被自己蠢哭) 我们观察到 0 <= f[i] <= 6 就简单了,就像小学初中学的 ...
- P1759 通天之潜水(不详细,勿看)(动态规划递推,组合背包,洛谷)
题目链接:点击进入 题目分析: 简单的组合背包模板题,但是递推的同时要刷新这种情况使用了哪些物品 ac代码: #include<bits/stdc++.h> using namespace ...
- 洛谷 P2144 [FJOI2007]轮状病毒
P2144 [FJOI2007]轮状病毒 题目描述 轮状病毒有很多变种.许多轮状病毒都是由一个轮状基产生.一个\(n\)轮状基由圆环上\(n\)个不同的基原子和圆心的一个核原子构成.\(2\)个原子之 ...
随机推荐
- MySQL 启停过程了解一二
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. GreatSQL是MySQL的国产分支版本,使用上与MySQL一致. 前言 你知道MySQL启停都做了些什么吗? 启动的时 ...
- 万答#9,MySQL 中有哪些常用的日志
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 前 ...
- 数据结构与算法【Java】02---链表
前言 数据 data 结构(structure)是一门 研究组织数据方式的学科,有了编程语言也就有了数据结构.学好数据结构才可以编写出更加漂亮,更加有效率的代码. 要学习好数据结构就要多多考虑如何将生 ...
- Pycharm5个非常有用的技巧
PyCharm 是一款非常强大的编写 python 代码的工具.掌握一些小技巧能成倍的提升写代码的效率,本篇介绍几个经常使用的小技巧. 一.分屏展示 当你想同时看到多个文件的时候: 右击标签页: 选择 ...
- 事物的隔离性和MVCC
事物的隔离性 mysql的服务端是支持多个客户端同时与之连接的,每个客户端可能还并发了好几个连接,所以mysql是需要同时处理很多事情的,每一件独立的事情就叫做事务.我们知道事务有一个叫隔离性的特性, ...
- Clickhouse基准测试实践
1.概述 本篇博客将对MySQL.InfluxDB.Clickhouse在写入时间.聚合查询时间.磁盘使用等方面的性能指标来进行比较. 2.内容 比较的数据集,是使用的Clickhouse官网提供的6 ...
- 7个自定义定时任务并发送消息至邮箱或企业微信案例(crontab和at)
前言 更好熟悉掌握at.crontab定时自定义任务用法. 实验at.crontab定时自定义任务运用场景案例. 作业.笔记需要. 定时计划任务相关命令及配置文件简要说明 at 工具 由包 at 提供 ...
- Html飞机大战(六):移动飞机
好家伙,这篇移动主角 我们先来看看一个好东西, addEventListener() 方法 (他真的很好用) 我们直译一下,就叫他添加事件监听器方法 而可监听的对象就有很多啦 我们来了解一 ...
- 没有二十年功力,写不出Thread.sleep(0)这一行“看似无用”的代码!
你好呀,我是喜提七天居家隔离的歪歪. 这篇文章要从一个奇怪的注释说起,就是下面这张图: 我们可以不用管具体的代码逻辑,只是单单看这个 for 循环. 在循环里面,专门有个变量 j,来记录当前循环次数. ...
- KingbaseES where 条件解析顺序
概述 KingbaseES 对于where 条件的解析严格遵守"从左到右"的原则,因此,对于选择性比较强的条件,进行最先过滤是有利于性能的. 一.KingbaseES 1.条件顺序 ...