面向物件、類、屬性
阿新 • • 發佈:2020-10-09
矩陣可以用二維陣列或者vector陣列來儲存,但是vector陣列的操作可能會有點慢,遇到TLE且矩陣大小比較固定的題目,及時轉換到二維陣列。至於快速冪的實現,與普通整數快速冪思想一樣。一個簡單例題POJ3734,用vector陣列實現
#include<stdio.h> #include<vector> using namespace std; typedef vector<int> vec; typedef vector<vec> mat; typedef long long ll; const int mod=10007; mat mul(mat &A,mat &B){ mat C(A.size(),vec(B[0].size())); for(int i=0;i<A.size();i++){ for(int k=0;k<B.size();k++){ for(int j=0;j<B[0].size();j++){ C[i][j]=(C[i][j]+A[i][k]*B[k][j])%mod; } } } return C; } mat pow(mat A,int n){ mat B(A.size(),vec(A.size())); for(int i=0;i<A.size();i++){ B[i][i]=1; } while(n!=0){ if(n%2==1) B=mul(B,A); A=mul(A,A); n/=2; } return B; } int main(){ int t; scanf("%d",&t); while(t--){ int n; scanf("%d",&n); mat A(3,vec(3)); A[0][0]=2;A[0][1]=1;A[0][2]=0; A[1][0]=2;A[1][1]=2;A[1][2]=2; A[2][0]=0;A[2][1]=1;A[2][2]=2; A=pow(A,n); printf("%d\n",A[0][0]); } return 0; }
搞清楚矩陣乘法的步驟,這一部分程式碼就比較容易。難點在於發現規律,以及將規律轉化為矩陣。對於普遍的遞推式,有矩陣形式:
若是遞推式中有常數項,對應地需要擴充套件矩陣:
POJ3735,對錶中元素執行一系列加減、清空、置換的操作,並重復多次,每一次指令可以用矩陣進行記錄,計算矩陣冪即可求解。但是這裡的A、T與不同矩陣不同,需要擴充套件,T有n+1個元素,第一個為1其他為0;A是(n+1)*(n+1)單位矩陣,根據操作進行變換
#include<stdio.h>
typedef long long ll;
const int N=105;
struct mat{
ll a[N][N];
void init(){
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
a[i][j]=0;
}
}
}
};
int n,m,k;
mat mul(mat A,mat B){
mat C;
C.init();
for(int i=0;i<=n;i++){
for(int k=0;k<=n;k++){
if(A.a[i][k]){
for(int j=0;j<=n;j++){
C.a[i][j]+=A.a[i][k]*B.a[k][j];
}
}
}
}
return C;
}
mat pow(mat A,int x){
mat B;
B.init();
for(int i=0;i<=n;i++){
B.a[i][i]=1;
}
while(x!=0){
if(x%2==1) B=mul(B,A);
A=mul(A,A);
x/=2;
}
return B;
}
int main(){
while(scanf("%d%d%d",&n,&m,&k)!=EOF){
if(n==0&&m==0&&k==0) break;
mat A;
A.init();
for(int i=0;i<=n;i++) A.a[i][i]=1;
char s[5];
int a,b;
while(k--){
scanf("%s%d",s,&a);
if(s[0]=='g') A.a[0][a]++;
else if(s[0]=='e'){
for(int i=0;i<=n;i++) A.a[i][a]=0;
}
else{
scanf("%d",&b);
for(int i=0;i<=n;i++){
int t=A.a[i][a];
A.a[i][a]=A.a[i][b];
A.a[i][b]=t;
}
}
}
mat T;
T.init();
T.a[0][0]=1;
T=mul(T,pow(A,m));
for(int i=1;i<=n;i++){
printf("%lld ",T.a[0][i]);
}
printf("\n");
}
return 0;
}
POJ3233,矩陣冪下一種獨特的型別,求S=A+A2+A3+...+An。
最後再記錄一道題,在圖中求長度為k的路徑總數。k=1時,鄰接矩陣就是最後的答案矩陣,遍歷矩陣求和即可。k>=1,最後的答案矩陣是鄰接矩陣的k次冪。