zoukankan      html  css  js  c++  java
  • HDU5411CRB and Puzzle(矩阵高速幂)

    题目链接:传送门 

    题意:

    一个图有n个顶点。已知邻接矩阵。问点能够反复用长度小于m的路径有多少。


    分析:

    首先我们知道了邻接矩阵A。那么A^k代表的就是长度为k的路径有多少个。

    那么结果就是A^0+A^1+A^2+...+A^m。

    然后我们能够构造一个矩阵来帮助我们求解。

    X = | A , E |  

        | 0 , E |

     ==> 然后X^m 的矩阵的右上角的矩阵代表的就是A^0+A^1+A^2+...+A^m。

    当然A^0+A^1+A^2+...+A^m,也能够用二分来求。


    代码例如以下:

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 51*2;
    
    const int mod = 2015;
    
    typedef long long LL;
    
    struct matrix{
        int a[maxn][maxn];
        matrix(){
            memset(a,0,sizeof(a));
        }
    };
    
    matrix I;
    
    void init(){
        for(int i=0;i<maxn;i++)
            I.a[i][i]=1;
    }
    
    int n,m;
    
    matrix multi(matrix A,matrix B){
        matrix C;
        for(int i=0;i<2*n;i++){
            for(int j=0;j<2*n;j++){
                for(int k=0;k<2*n;k++){
                    C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j]);
                }
                C.a[i][j]%=mod;
            }
        }
        return C;
    }
    
    matrix add(matrix A,matrix B){
        matrix C;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                C.a[i][j]=(A.a[i][j]+B.a[i][j])%mod;
            }
        }
        return C;
    }
    
    int quick_mod(matrix A,int b){
        matrix ans = I;
        while(b){
            if(b&1) ans = multi(ans,A);
            b>>=1;
            A=multi(A,A);
        }
        int sum = 0;
        for(int i=0;i<n;i++){
            for(int j=n;j<n*2;j++)
                sum=sum+ans.a[i][j];
        }
    //    cout<<"----------ans------------"<<endl;
    //    for(int i=0;i<2*n;i++){
    //        for(int j=0;j<2*n;j++)
    //            cout<<ans.a[i][j]<<" ";
    //        cout<<endl;
    //    }
    //    cout<<"----------ans------------"<<endl;
        return sum%mod;
    }
    
    int main()
    {
        init();
        int t;
        scanf("%d",&t);
        while(t--){
            scanf("%d%d",&n,&m);
            matrix A,B;
            for(int i=0;i<n;i++){
                int k,u;
                scanf("%d",&k);
                while(k--){
                    scanf("%d",&u);
                    A.a[i][--u]=1;
                }
            }
            for(int i=0;i<n;i++) A.a[i][i+n]=1;
            for(int i=n;i<2*n;i++) A.a[i][i]=1;
    //        cout<<"----------A------------"<<endl;
    //        for(int i=0;i<2*n;i++){
    //            for(int j=0;j<2*n;j++)
    //                cout<<A.a[i][j]<<" ";
    //            cout<<endl;
    //        }
    //        cout<<"----------A------------"<<endl;
            int sum = quick_mod(A,m);
            printf("%d
    ",sum+1);
        }
        return 0;
    }
    


  • 相关阅读:
    乱七八糟
    堆-heap
    转linux文件的读写
    @转EXT2->EXT3->EXT4
    (转)僵死进程与孤儿进程
    java
    poj-1062-昂贵的聘礼
    java 之 wait, notify, park, unpark , synchronized, Condition
    事物(笔记)
    BPX-tree
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7086947.html
Copyright © 2011-2022 走看看