题目链接:https://vijos.org/p/1049
题目大意: 顺次给出m个置换,反复使用这m个置换对初始序列进行操作,问k次置换后的序列。m<=10, k<2^31。
注意:
在写矩阵的乘法的时候一定要注意,写好到底是谁乘以谁。写反了就悲剧了。
还有,在求快速幂取模的时候要用非递归写法,不然容易RE;
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; #define Nnum 31 #define Mnum 31 #define LL long long struct matrix { int n,m; int mat[101][101]; matrix() { memset(mat,0,sizeof(mat)); } matrix operator+(const matrix& B)const { int i,j; matrix A; A.n=n; A.m=m; for(i=1; i<=n; i++) for(j=1; j<=m; j++)A.mat[i][j]=mat[i][j]+B.mat[i][j]; return A; } }M[11]; matrix mul(matrix A,matrix B) { int i,j,k,nn,mm; matrix C; nn=A.n; mm=B.m; C.m=mm; C.n=nn; for(i=1; i<=nn; i++) { for(j=1; j<=mm; j++) { C.mat[i][j]=0; for(k=1; k<=A.m; k++) { C.mat[i][j]+=A.mat[i][k]*(B.mat[k][j]); } } } return C; } matrix powmul(matrix A,int k) { matrix B; B.n=A.n; B.m=A.m; for(int i=1; i<=min(B.n,B.m); i++)B.mat[i][i]=1; while(k>=1) { if(k&1)B=mul(A,B); A=mul(A,A); k=k/2; } return B; } int main() { int i,j,n,m,k,a; scanf("%d%d%d",&n,&m,&k); memset(M,0,sizeof(M)); matrix A; matrix ans; A.n=A.m=n; ans.n=n; ans.m=1; for(i=1; i<=n; i++)A.mat[i][i]=1,ans.mat[i][1]=i; for(i=1; i<=m; i++) { M[i].n=M[i].m=n; for(j=1; j<=n; j++) { scanf("%d",&a); M[i].mat[j][a]=1; } A=mul(M[i],A); } int num=k/m; k=k%m; A=powmul(A,num); for(i=1; i<=k; i++)A=mul(M[i],A); A=mul(A,ans); for(i=1; i<=n; i++) { if(i!=1)cout<<" "; cout<<A.mat[i][1]; } return 0; }