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\)个原子之 ...
随机推荐
- 关于微信小程序生产环境体验版获取不到openId的问题(大坑)
原文转载自「刘悦的技术博客」https://v3u.cn/a_id_119 我们知道openid是微信用户验证的重要标识,支付功能严重依赖这个东西,之前我们做微信支付的时候是通过在微信客户端直接调用官 ...
- google nexus5x 刷机抓包逆向环境配置(一)
本文仅供学习交流使用,如侵立删! google nexus5x 刷机抓包逆向环境配置(一) 操作环境 nexus5x kaliLinux win10 准备 官方工具包官方下载地址:https://dl ...
- Docker容器网络配置
Docker容器网络配置 1.Linux内核实现名称空间的创建 1.1 ip netns命令 可以借助ip netns命令来完成对 Network Namespace 的各种操作.ip netns命令 ...
- MySQL更新锁表超时 Lock wait timeout exceeded
背景 最近在做一个订单的钉钉审批功能,钉钉审批通过之后,订单更新审核状态,然后添加一条付款,并且更新付款状态: // 订单审批通过 @Transactional(rollbackFor = Excep ...
- Redis 哨兵机制
概述 由一个或多个 Sentinel(哨兵)实例组成的 Sentinel 系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器,并在被监视的主服务器进入下线状态时,自动将下线主服务器属下的 ...
- Python自学笔记6-列表有哪些常用操作
列表是Python中最重要的数据类型,它使用的频率非常非常的高,最大程度的发挥Python的灵活性. 和字符串一样,列表的操作方法也有很多.如果说一头钻进去,可能会导致学习没有重点.在这篇文章当中,首 ...
- [HNOI2016]最小公倍数 (可回退并查集,回滚莫队)
题面 题目链接 题目描述 给定一张 N N N 个顶点 M M M 条边的无向图(顶点编号为 1 , 2 , - , n 1,2,\ldots,n 1,2,-,n),每条边上带有权值.所有权值都可以分 ...
- Python入门系列(八)日期时间、数学、json
日期时间 Python中的日期本身不是数据类型,但我们可以导入一个名为datetime的模块,将日期作为日期对象使用. import datetime x = datetime.datetime.no ...
- 【读书笔记】C#高级编程 第二十一章 任务、线程和同步
(一)概述 所有需要等待的操作,例如,因为文件.数据库或网络访问都需要一定的时间,此时就可以启动一个新的线程,同时完成其他任务. 线程是程序中独立的指令流. (二)Paraller类 Paraller ...
- Android开发2021.3.9日【模拟器路径】【外观字体】【简单快捷键】
一. 1.模拟器存储路径 D:\Android\SDK\platforms(在本人的dell上) 2.使用软件 Android Studio4.2 3.注意事项 (1)修改JDK的路径为自己下载的JD ...