zoukankan      html  css  js  c++  java
  • BZOJ 1002 轮状病毒

       这是很久前看到的题了,一直不知如何下手,有一段时间误解了。直到前天决定对这道题下手了。去百度了一下,有人说是和基尔霍夫矩阵有关,也有人曾说和卢卡斯数列有关。

        一开始看了基尔霍夫矩阵,真的是一脸茫然,这是怎么解决这道题的呢!后来仔细看了题目,的确这可以算是一道生成树的计数问题。(因为任意两点间都只有一条通路)。那么基尔霍夫矩阵便是解决这一问题的方法。

      首先,基尔霍夫矩阵是有一个无向图的度矩阵对应地减去一个图的邻接矩阵得到的。如图,这是个无向图。 第二个图是它的度矩阵(度矩阵只有当 i == j 的时候 a[i][j]才有值,其他都为0 );  

      第三个图是邻接矩阵,第四个图便是基尔霍夫矩阵。

                

       生成矩阵之后,要接着得到它的 n-1 阶主子式(即该n阶矩阵同时去掉第r行,第r列得到的,其中r为任意小于n大于0的一个整数);

       最后要对其进行高斯消元得到他的三角形行列式(上三角矩阵)即主对角线下面的数都为0。最后将主对角线上的数都乘起来,便是最终结果。然而蒟蒻并不会证明。

       通过基尔霍夫矩阵得出比较小的一些值后,就可以开始找规律了。最终得出的递推式是 F[n] = F[n-1]*3-F[n-2]+2;(从网上的许多题解中很多人都涉及到一点,如果遇到这种题,很有可能是要递推找规律的);

       以下是基尔霍夫矩阵的代码。ca为输入数据组数,n为图的总点数,m为图的总边数。

       

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #define rep(i,j,k) for(int i = j; i <= k; i++)
     5 #define maxn 25
     6 #define LL long long
     7 using namespace std;
     8 
     9 LL c[maxn][maxn] = {0}, n, m;
    10 
    11 int read()
    12 {
    13     int s = 0, t = 1; char c = getchar();
    14     while( !isdigit(c) ){
    15         if( c == '-' ) t = -1; c = getchar();
    16     }
    17     while( isdigit(c) ){
    18         s = s * 10 + c - '0'; c = getchar();
    19     }
    20     return s * t;
    21 }
    22 
    23 LL det()
    24 {
    25     LL ans = 1;
    26     rep(i,1,n-1){
    27         rep(j,i+1,n-1){
    28             while( c[j][i] ){
    29                 LL f = c[i][i] / c[j][i];
    30                 if( f ) {
    31                     rep(l,i,n-1) c[i][l] -= f * c[j][l];
    32                 }
    33                 rep(l,i,n-1) swap(c[i][l],c[j][l]);
    34             }
    35         }
    36         ans *= c[i][i];
    37         if( !ans ) return 0;
    38     }
    39     return ans < 0? -ans : ans;
    40 }
    41 
    42 int main()
    43 {
    44     int ca = read();
    45     while( ca-- ){
    46         memset(c,0,sizeof(c));
    47         n = read(), m = read();
    48         rep(i,1,m){
    49             int u = read(), v = read();
    50             u--, v--;
    51             c[u][u]++, c[v][v]++;
    52             c[u][v]--, c[v][u]--;
    53         }
    54         cout<<det();
    55     }
    56     return 0;
    57 }

         以下是BZOJ 1002的代码

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #define rep(i,j,k) for(int i = j; i <= k; i++)
     5 #define down(i,j,k) for(int i = j; i >= k; i--)
     6 #define maxn 110
     7 using namespace std;
     8 
     9 int mol = 10000;
    10 
    11 int read()
    12 {
    13     int s = 0, t = 1; char c = getchar();
    14     while( !isdigit(c) ){
    15         if( c == '-' ) t = -1; c =getchar();
    16     }
    17     while( isdigit(c) ){
    18         s = s * 10+ c - '0'; c = getchar();
    19     }
    20     return s * t;
    21 }
    22 
    23 struct data{
    24 int a[40];
    25 data(){
    26   memset(a,0,sizeof(a));
    27 }
    28 };
    29 
    30 data datas[maxn];
    31 
    32 data mul(data a,int b)
    33 {
    34     rep(i,1,a.a[0]){
    35         a.a[i] *= b;
    36     }
    37     rep(i,1,a.a[0]+2){
    38         a.a[i+1] += a.a[i] / mol;
    39         a.a[i] %= mol;
    40     }
    41     while( a.a[a.a[0]+1] ){
    42         a.a[0]++;
    43     }
    44     return a;
    45 }
    46 
    47 data sub(data a,data b)
    48 {
    49     a.a[1] += 2;
    50     down(i,a.a[0],1){
    51         if( a.a[i] < b.a[i] ){
    52             a.a[i+1]--, a.a[i] += mol;
    53         }
    54         a.a[i] -= b.a[i];
    55     }
    56     while( !a.a[a.a[0]] ) {
    57         a.a[0]--;
    58     }
    59     return a;
    60 }
    61 
    62 int main()
    63 {
    64     int n = read();
    65     datas[1].a[0] = datas[2].a[0] = 1;
    66     datas[1].a[1] = 1, datas[2].a[1] = 5;
    67     rep(i,3,n){
    68         datas[i] = sub(mul(datas[i-1],3),datas[i-2]);
    69     }
    70     int s = datas[n].a[0];
    71     printf("%d", datas[n].a[s]);
    72     down(i,s-1,1){
    73         printf("%04d", datas[n].a[i] );
    74     }
    75     cout<<endl;
    76     return 0;
    77 }
    人一我十,人十我万!追逐青春的梦想,怀着自信的心,永不放弃!仿佛已看到希望,尽管还在远方
  • 相关阅读:
    VBA中使用计时器的两种方法
    好的关卡离不开优秀的团队
    如何从无到有做一个好关卡?
    性能优化总结
    用超链接提交表单,实现在动态网页的url中隐藏参数
    js 中使用el表达式 关键总结:在js中使用el表达式一定要使用双引号
    js中getBoundingClientRect的作用及兼容方案
    IE10、IE11和Microsoft Edge的Hack
    CSS Hack大全-教你如何区分出IE6-IE10、FireFox、Chrome、Opera
    点击a标签,跳转到iframe中,并在iframe中显示指定的页面
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5053939.html
Copyright © 2011-2022 走看看