vijos1049 矩阵乘法

题意

给你一个物品变换的顺序表,然后让你求变换了次之后物品的位置(n<=100, m<=10, k<=1e9)

分析

矩阵的妙用啊(0/1矩阵与原矩阵相乘即是变化结果),将每一行变化转化为一个0/1矩阵,所以m个变化可以转为为m个矩阵相乘,但矩阵乘法不符合交换律,符合结合律,所以必须将矩阵转置,分为k/m快速幂、k%m暴力模拟即可

#include <iostream>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<vector>
#include<cstring>
#include<algorithm>
#define FOR(i,x,y) for(i=x;i<=y;++i)
#define maxn 1005
using namespace std;
int n,m,k;

struct matrix{
    int mtx[105][105];
}mx[13];

matrix mul(matrix a, matrix b){
    matrix ret;
    memset(ret.mtx, 0, sizeof(ret.mtx));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            for(int k=1;k<=n;k++){
                ret.mtx[i][j]+=a.mtx[i][k]*b.mtx[k][j];
            }
        }
    }
    return ret;
}



matrix qpow(matrix a, int n)
{
    if(!n) return a;
    matrix ret=a;
    n--;
    while(n)
    {
        if(n&1)  ret=mul(ret, a);
        a=mul(a,a);
        n>>=1;
    }
    return ret;
}

int main()
{
    scanf("%d%d%d", &n, &m, &k);
    int x;
    for(int i=1;i<=m;i++){
        for(int j=1;j<=n;j++){
            scanf("%d", &x);
            mx[i].mtx[x][j]=1;
        }
    }

    matrix ans=mx[1];
    for(int i=2;i<=m;i++){
        ans=mul(ans,mx[i]);
    }
    ans=qpow(ans,k/m);
    k%=m;
    for(int i=1;i<=k;i++){
        ans=mul(ans,mx[i]);
    }
    matrix st;
    for(int i=1;i<=n;i++){
        st.mtx[1][i]=i;
    }
    st=mul(st, ans);
    for(int i=1;i<=n;i++){
        printf("%d ", st.mtx[1][i]);
    }
    printf("
");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/Superwalker/p/8567054.html