首页 > 代码库 > HDU5411CRB and Puzzle(矩阵高速幂)

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\n",sum+1);
    }
    return 0;
}


HDU5411CRB and Puzzle(矩阵高速幂)