HDU5411CRB and Puzzle(矩陣高速冪)
阿新 • • 發佈:2017-06-27
結果 -m sizeof oid ont con tracking code long
題目鏈接:傳送門
題意:
一個圖有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(矩陣高速冪)