hdu 2157 (矩陣快速冪)
阿新 • • 發佈:2019-02-01
把給定的圖轉為鄰接矩陣,即A(i,j)=1當且僅當存在一條邊i->j。令C=A*A,那麼C(i,j)=ΣA(i,k)*A(k,j),實際上就等於從點i到點j恰好經過2條邊的路徑數(列舉k為中轉點)。類似地,C*A的第i行第j列就表示從i到j經過3條邊的路徑數。
通過將矩陣連乘的過程模擬出來,模擬一遍就懂了。
#include<bits/stdc++.h> using namespace std; typedef long long int ll; const ll mod = 1000; const int maxn=22; //自己看情況定義 //定義矩陣乘法 struct matrix{ ll arr[maxn][maxn]; matrix operator*(matrix b){ matrix ans; ll tmp; for(int i=0; i<maxn; i++) for(int j=0; j<maxn; j++){ ans.arr[i][j] = 0; for(int k=0; k<maxn; k++){ tmp = (arr[i][k]*b.arr[k][j])%mod; ans.arr[i][j] = (ans.arr[i][j] + tmp)%mod; //cout<<"oh"<<endl; } } return ans; } }; //矩陣快速冪 matrix quick_pow(matrix a,ll N){ matrix ans; memset(ans.arr,0,sizeof(ans.arr)); for(int i=0; i<maxn; i++) ans.arr[i][i] = 1; while(N){ if(N&1) ans = ans*a; a = a*a; N /= 2;; } return ans; } int main(){ matrix a; int n,m; while(scanf("%d%d",&n,&m)&&(n+m)){ memset(a.arr,0,sizeof(a.arr)); int x,y; for(int i=0;i<m;i++){ scanf("%d%d",&x,&y); a.arr[x][y]=1ll; } int t; ll k; scanf("%d",&t); for(int i=0;i<t;i++){ scanf("%d%d%lld",&x,&y,&k); matrix ans=quick_pow(a,k); printf("%d\n",ans.arr[x][y]); } } return 0; }