TOJ 3848 Game 矩阵快速幂

本文解析了一道关于矩阵快速幂的算法竞赛题目,通过函数实现与类的封装两种方式展示了如何解决该问题。介绍了矩阵的基本操作如初始化、乘法及快速幂运算,并通过具体示例说明了算法的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Perhaps there is three people:

                                                            1    2    3

(S1,S2,S3) = (S1,S2,S3)( 2    1    2)^ N

                                                             0    3    1

The first column is s1 vs s1, s1 vs s2,s1 vs s3;

The scond column is s2 vs s1 ,s2 vs s2 ,s2 vs s3;

The third column is s3 vs s1 ,s3 vs s2 ,s3 vs s3;

The portal:http://acm.tju.edu.cn/toj/showp3848.html

函数版:

//TOJ 3849

#include <cstdio>
#include <cstring>
#include <cstdlib>

int Len_Matrix;
int Mod;

struct Matrix {
    int M[55][55];
};

void Init_Matrix(Matrix & tmp) {
    for(int i = 1 ; i <= Len_Matrix ; i++) {
        for(int j = 1 ; j <= Len_Matrix ; j++) {
            if(i == j)tmp.M[i][j] = 1;
            else tmp.M[i][j] = 0;
        }
    }
}

void Debug(Matrix tmp) {
    for(int i = 1 ; i <= Len_Matrix ; i ++) {
        for(int j = 1 ; j <= Len_Matrix ; j ++) {
            printf("%d ",tmp.M[i][j]);
        }
        puts("");
    }
    puts("");
}

Matrix Multiply(Matrix a1,Matrix a2) {
    Matrix ans ;
    Init_Matrix(ans);
    for(int i = 1 ; i <= Len_Matrix ; i++) {
        for(int j = 1 ; j <= Len_Matrix ; j++) {
            int temp_ans  = 0;
            for(int k = 1 ; k <= Len_Matrix ; k++) {
                temp_ans = (temp_ans + a1.M[i][k] * a2.M[k][j])%Mod; 
            }
            ans.M[i][j] = temp_ans;
        }
    }
    return ans;
}

Matrix Pow(Matrix a1,int n) {
    Matrix ans ;
    Init_Matrix(ans);
    while(n) {
        if(n&1) ans = Multiply(ans,a1);
        a1 = Multiply(a1,a1);
        n >>= 1;
    }
    return ans;
}

void Deal_with() {
    int T;
    scanf("%d",&T);
    while(T--) {
        int M,P,N;
        scanf("%d %d %d",&M,&P,&N);
        Matrix tmp;
        Matrix ss;
        Mod = P;
        Len_Matrix = M;
        int id,init_value,K,d_id,d_times;
        Init_Matrix(tmp);
        for(int i = 1 ; i <= M ; i++ ) {
            scanf("%d %d %d",&id,&init_value,&K);
            ss.M[1][id] = init_value;
            for(int j = 1 ; j <=  K ; j ++) {
                scanf("%d %d",&d_id,&d_times);
                tmp.M[d_id][id] = d_times;
            }
        }
        for(int i = 2 ; i <= M ; i++ ) {
            for(int j = 1 ; j <= M ; j++){
                ss.M[i][j] = 0;
            }
        }
        Matrix ans;
        ans = Pow(tmp,N);
        //Debug(ans);
        ans = Multiply(ss,ans);
        //Debug(ans);
        int max_score = -1;
        for(int i = 1 ; i <= M ; i++) {
            if(ans.M[1][i] > max_score) max_score = ans.M[1][i];
        }
        printf("%d\n",max_score);
    }
}

int main(void) {
    //freopen("a.in","r",stdin);
    Deal_with();
    return 0;
}

用类的重构版:

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>

int Mod ;

class Matrix {
public:
    int M[55][55];
    int Len_Matrix;
    Matrix(){memset(M,0,sizeof(M));}
    Matrix(int Len_Matrix_) : Len_Matrix(Len_Matrix_) {
        memset(M,0,sizeof(M));
        for(int i = 1 ; i <= Len_Matrix ; i++ ) {
            M[i][i]  = 1;
        }
    }
    Matrix operator * (const Matrix a) const {
        Matrix b;
        b.Len_Matrix = Len_Matrix;
        for(int i = 1 ; i <= Len_Matrix ; i ++) {
            for(int j = 1 ; j <= Len_Matrix ; j++) {
                for(int k = 1 ; k <= Len_Matrix ; k++) {
                    b.M[i][j] = (b.M[i][j] + M[i][k] * a.M[k][j] ) % Mod; 
                }   
            }
        } 
        return b;
    }
    Matrix operator ^ (const int n) const {
        Matrix ans(Len_Matrix);
        Matrix base = * this;
        int k = n;
        while(k) {
            if(k & 1) ans = ans * base;
            base = base * base;
            k >>= 1;
        }
        //ans.Debug();
        return ans;
    }
    void Debug() {
        printf("Len_Matrix : %d\n",Len_Matrix);
        for(int i = 1 ; i <= Len_Matrix ; i++) {
            for(int j = 1 ; j <= Len_Matrix ; j++) {
                printf("%d ",M[i][j]);
            }
            puts("");
        }
        puts("");
    }
};

void Deal_with() {
    int T;
    scanf("%d",&T);
    while(T--) {
        int M,P,N;
        scanf("%d %d %d",&M,&P,&N);
        Mod = P;
        Matrix tmp(M);
        //tmp.Debug();
        Matrix ss;
        ss.Len_Matrix = M;
        int id,init_value,K,d_id,d_times;
        for(int i = 1 ; i <= M ; i++ ) {
            scanf("%d %d %d",&id,&init_value,&K);
            ss.M[1][id] = init_value;
            for(int j = 1 ; j <=  K ; j ++) {
                scanf("%d %d",&d_id,&d_times);
                tmp.M[d_id][id] = d_times;
            }
        }
        Matrix ans;
        //printf("Len_Matrix : %d M : %d\n",ans.Len_Matrix,M);
        ans.Len_Matrix = M;
        //printf("Len_Matrix : %d M : %d\n",ans.Len_Matrix,M);
        //ans.Debug();
        ans = tmp ^ N;
        //ans.Debug();
        ans = ss * ans;
        //ans.Debug();
        int max_score = -1;
        for(int i = 1 ; i <= M ; i++) {
            if(ans.M[1][i] > max_score) max_score = ans.M[1][i];
        }
        printf("%d\n",max_score);
    }
}

int main(void) {
    //freopen("a.in","r",stdin);
    Deal_with();
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值