BZOJ 2467: [中山市选2010]生成树(矩阵树定理+取模高斯消元)
2017-08-14 22:16
357 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=2467
题意:
思路:
要用矩阵树定理不难,但是这里的话需要取模,所以是需要计算逆元的,但是用辗转相减会更简单。
引用一大神博客里的介绍:http://blog.csdn.net/u013010295/article/details/47451451
值得一提的是,有些题目要求行列式模上一个数的结果。怎么求模意义下的行列式呢?这些题答案都比较大,用浮点数的话精度达不到要求,确实是一个问题。(显然强行用高精度分数类直接消元,最后再取模是可以的,但实现起来就复杂了)
我们注意到最后行列式是主对角线上的元素乘积再取模,根据同余定理,我们只需要对这些元素取模后的结果再相乘,就能得到相同的结果。因此我们可以采用在模意义下对矩阵消元的方法。然而消元过程中我们不可避免地要计算当前列的主元间的比值,这要用到除法;但另一方面,只有加法、减法、乘法操作才能保证同余,怎么在带有除法操作的条件下取模呢?
如果模的数是个质数(其实只需要模数和除数互质),对于除法我们可以直接变成乘上除数的逆元,根据费马小定理,这个逆元可以用快速幂简单求出来。如果模数不是质数,这就比较复杂了,我们在此介绍一种简单的方法。
我们知道,如果对于两个正数,不断地把较大的数减去较小的数,最后一定会有一个数为0。你可能已经知道,这就是辗转相减法的过程。同样地,我们对于矩阵中的两行,不断地把主元较大的那一行减去主元较小的那一行,最终一定有一行主元为0,也就是完成了消元(注意这里的减法是模意义下的减法)。而且这一过程是不改变行列式的。
(需要说明的是,一般情况下,矩阵中可能会有主元为负数的情况,这时我们简单的“大数减小数”显然是不行了。你可能会想到,要对正负数的各种情况判断一下,分别改为加法和减法操作。然而,这里我们讨论的是模意义下的矩阵消元,矩阵的元素都是正整数,并不存在这个问题。)
这样的减法效率还不够高,显然,如果两个主元相差太大,我们需要不断地用一行减去另一行。我们可以记录下两个主元相除的商x(这里用的是整数除法,当不能整除的时候向上向下取整都可以,由于计算机内部的整数除法实现,我们一般是向下取整,而且也符合我们取商的直觉,下面复杂度计算的是向下取整的做法),一次性用主元较大的行减去主元较小的行乘上x倍,这样效率就大大提高了。我们这样做的复杂度是多少呢?其实你也许已经发现,这一过程实际上就是辗转相除法,所以时间复杂度是O(log(n))的。
题意:
思路:
要用矩阵树定理不难,但是这里的话需要取模,所以是需要计算逆元的,但是用辗转相减会更简单。
引用一大神博客里的介绍:http://blog.csdn.net/u013010295/article/details/47451451
值得一提的是,有些题目要求行列式模上一个数的结果。怎么求模意义下的行列式呢?这些题答案都比较大,用浮点数的话精度达不到要求,确实是一个问题。(显然强行用高精度分数类直接消元,最后再取模是可以的,但实现起来就复杂了)
我们注意到最后行列式是主对角线上的元素乘积再取模,根据同余定理,我们只需要对这些元素取模后的结果再相乘,就能得到相同的结果。因此我们可以采用在模意义下对矩阵消元的方法。然而消元过程中我们不可避免地要计算当前列的主元间的比值,这要用到除法;但另一方面,只有加法、减法、乘法操作才能保证同余,怎么在带有除法操作的条件下取模呢?
如果模的数是个质数(其实只需要模数和除数互质),对于除法我们可以直接变成乘上除数的逆元,根据费马小定理,这个逆元可以用快速幂简单求出来。如果模数不是质数,这就比较复杂了,我们在此介绍一种简单的方法。
我们知道,如果对于两个正数,不断地把较大的数减去较小的数,最后一定会有一个数为0。你可能已经知道,这就是辗转相减法的过程。同样地,我们对于矩阵中的两行,不断地把主元较大的那一行减去主元较小的那一行,最终一定有一行主元为0,也就是完成了消元(注意这里的减法是模意义下的减法)。而且这一过程是不改变行列式的。
(需要说明的是,一般情况下,矩阵中可能会有主元为负数的情况,这时我们简单的“大数减小数”显然是不行了。你可能会想到,要对正负数的各种情况判断一下,分别改为加法和减法操作。然而,这里我们讨论的是模意义下的矩阵消元,矩阵的元素都是正整数,并不存在这个问题。)
这样的减法效率还不够高,显然,如果两个主元相差太大,我们需要不断地用一行减去另一行。我们可以记录下两个主元相除的商x(这里用的是整数除法,当不能整除的时候向上向下取整都可以,由于计算机内部的整数除法实现,我们一般是向下取整,而且也符合我们取商的直觉,下面复杂度计算的是向下取整的做法),一次性用主元较大的行减去主元较小的行乘上x倍,这样效率就大大提高了。我们这样做的复杂度是多少呢?其实你也许已经发现,这一过程实际上就是辗转相除法,所以时间复杂度是O(log(n))的。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<sstream> #include<vector> #include<stack> #include<queue> #include<cmath> #include<map> #include<set> using namespace std; typedef long long ll; typedef pair<int,ll> pll; const int INF = 0x3f3f3f3f; const int maxn=500+5; int n; int C[maxn][maxn]; int Gauss() { for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) C[i][j]=(C[i][j]+2007)%2007; int ans=1; for(int i=1;i<=n;i++) //当前行 { for(int j=i+1;j<=n;j++) //当前行之后的每一行 { while(C[j][i]) //利用gcd的方法,不停地进行辗转相除 { int tmp=C[i][i]/C[j][i]; for(int k=i;k<=n;k++) C[i][k]=(C[i][k]-tmp*C[j][k])%2007; for(int k=i;k<=n;k++) swap(C[i][k],C[j][k]); ans=-ans; } } if(C[i][i]==0) return 0; ans=(ans*C[i][i])%2007; } ans=(ans+2007)%2007; return ans; } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while(T--) { memset(C,0,sizeof(C)); scanf("%d",&n); int cnt=n; for(int i=1;i<=n;i++) { C[i][i]+=4; C[i][i%n+1]+=-1; C[i][(i-1)>=1?i-1:n]+=-1; } for(int i=1;i<=n;i++) { cnt++; C[i][cnt]=C[cnt][i]+=-1; C[cnt][cnt]+=2; C[cnt][cnt+1]+=-1; C[cnt+1][cnt]+=-1; cnt++; C[cnt][cnt]+=2; C[cnt][cnt+1]+=-1; C[cnt+1][cnt]+=-1; cnt++; C[cnt][cnt]+=2; C[cnt][i%n+1]+=-1; C[(i+1)<=n?i+1:1][cnt]+=-1; } n=cnt-1; printf("%d\n",Gauss()); } return 0; }
相关文章推荐
- 【BZOJ】【P2467】【中山市选2010】【生成树】【题解】【矩阵树定理+高斯消元+打表】
- bzoj 4031: [HEOI2015]小Z的房间 (矩阵树定理+高斯消元)
- [bzoj2467][中山市选2010]生成树(ksm乱搞)
- [BZOJ3503]-[CQOI2014]和谐矩阵-高斯消元
- 【BZOJ3168】[Heoi2013]钙铁锌硒维生素 高斯消元求矩阵的逆+匈牙利算法
- 【bzoj2467】【中山市选2010】【生成树】【组合数学】
- bzoj 1778 [Usaco2010 Hol]Dotp 驱逐猪猡(高斯消元)
- BZOJ2467 [中山市选2010]生成树
- BZOJ2467 [中山市选2010]生成树
- BZOJ 2115|WC 2010|Xor|高斯消元
- 【BZOJ3659】Which Dreamed It【有向图欧拉回路计数】【matrix tree定理】【BEST定理】【高斯消元】
- BZOJ 3503: [Cqoi2014]和谐矩阵( 高斯消元 )
- [bzoj4031][HEOI2015]小Z的房间【矩阵树定理】【高斯消元】
- [BZOJ2467][中山市选2010]生成树(组合数学)
- [BZOJ1923][SDOI2010]外星千足虫(高斯消元---异或方程组)
- 【BZOJ 3503】 [Cqoi2014]和谐矩阵|高斯消元|xor方程组
- [AC自动机 概率DP 矩阵乘法||高斯消元] BZOJ 1444 [Jsoi2009]有趣的游戏
- 【中山市选2009】树 bzoj 2466/jzoj 2183 高斯消元求异或方程
- bzoj1778: [Usaco2010 Hol]Dotp 驱逐猪猡(概率DP+高斯消元)
- bzoj 1923: [Sdoi2010]外星千足虫 高斯消元