HDU5411CRB and Puzzle(矩陣快速冪)

bigbigship發表於2015-08-21

題目連結:傳送門 

題意:

一個圖有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;
}


相關文章