矩阵十大经典题目之四- VOJ1049-送给圣诞夜的礼品

题目链接: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;
}


你可能感兴趣的:(矩阵十大经典题目之四- VOJ1049-送给圣诞夜的礼品)