ACdream 1213 Matrix Multiplication(矩阵乘法)

本文探讨了解决涉及矩阵转置、矩阵乘法及关联矩阵等数学概念的复杂问题,通过对比初始直接方法和优化后的算法实现,揭示了如何避免MLE错误并提升程序效率。重点介绍了从直接实现到采用更高效策略的转变过程,以及如何利用矩阵操作的性质来简化计算。此文章旨在为读者提供一种在处理类似问题时更加高效和精确的方法。

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

题目链接:http://acdream.info/problem?pid=1213

涉及的数学知识较多,包括矩阵的转置,矩阵的乘法,关联矩阵.....

刚开始是直接按照各个概念做的,结果MLE了,MLE代码如下

#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
using namespace std;
int n,m;
int a[10005][5],v[10005][10005],v1[10005][10005];
int main()
{
    int i,j;
    while(~scanf("%d%d",&n,&m))
    {
        memset(v,0,sizeof(v));
        memset(v1,0,sizeof(v1));
        for(i=0;i<m;i++)
            for(j=0;j<2;j++)
            scanf("%d",&a[i][j]);
        for(i=0;i<m;i++)
            v[a[i][0]-1][a[i][1]-1]=v[a[i][1]-1][a[i][0]-1]=1;
        for(i=0;i<n;i++)
            for(j=0;j<m;j++)
                v1[j][i]=v[i][j];
        int sum=0,b=0,k=m;
        while(k--)
        {
             for(i=0;i<n;i++)
            {
                int c=0;
                for(j=0;j<m;j++)
                {
                    sum+=v[b][c++]*v1[j][i];
                }
            }
            b++;
        }
        printf("%d\n",sum);
    }
    return 0;
}

网上看了别人的题解后获得思路,下面是AC代码

#include<cstdio>
#include<iostream>
#include<sstream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<climits>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<set>
#include<map>
using namespace std;
int n,m;
int a[100005];
int main()
{
    int i,j;
    while(~scanf("%d%d",&n,&m))
    {
        int u,v;
        memset(a,0,sizeof(v));
        for(i=1; i<=m; i++)
        {
            scanf("%d%d",&u,&v);
            a[u]++;
            a[v]++;
        }
        long long sum=0;
        for(i=1; i<=n; i++)
            sum+=a[i]*a[i];
        printf("%lld\n",sum);
    }
    return 0;
}



### Hadoop中的矩阵相乘实现 在Hadoop框架下,矩阵相乘可以通过MapReduce来高效完成。以下是基于Hadoop MapReduce的一个典型矩阵相乘示例代码。 #### 输入数据格式 假设输入文件存储的是两个矩阵的数据,每行表示一个元素的位置及其值。例如: - 对于矩阵A (m × r),每一行的格式为 `A i j value` 表示第i行第j列的值。 - 对于矩阵B (r × n),每一行的格式为 `B k l value` 表示第k行第l列的值。 #### Mapper逻辑 Mapper的任务是将矩阵A和矩阵B的元素转换成键值对形式 `(key, value)`,其中key是由输出矩阵C的行列索引组成的元组`(row_C, col_C)`。 对于矩阵A的元素 `(i, j, val_Aij)` 和矩阵B的元素 `(k, l, val_Bkl)`: - 如果当前处理的是矩阵A,则生成 `<(i,l), ("A", j, val_Aij)>` 的中间键值对。 - 如果当前处理的是矩阵B,则生成 `<(i,l), ("B", k, val_Bkl)>` 的中间键值对。 ```java public class MatrixMultiplyMapper extends Mapper<LongWritable, Text, IntPairWritable, Text> { private static final String MATRIX_A = "A"; private static final String MATRIX_B = "B"; @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String[] tokens = value.toString().split("\\s+"); int row = Integer.parseInt(tokens[1]); int col = Integer.parseInt(tokens[2]); double val = Double.parseDouble(tokens[3]); if (tokens[0].equals(MATRIX_A)) { // Process A[i][j] for(int l=0; l<n; ++l){ // Assuming 'n' is predefined as number of columns in B. context.write(new IntPairWritable(row, l), new Text(MATRIX_A + "," + col + "," + val)); } } else if (tokens[0].equals(MATRIX_B)) { // Process B[k][l] for(int i=0; i<m; ++i){ // Assuming 'm' is predefined as number of rows in A. context.write(new IntPairWritable(i, col), new Text(MATRIX_B + "," + row + "," + val)); } } } } ``` #### Reducer逻辑 Reducer接收来自Mapper的相同key的所有value列表,并计算最终的结果矩阵C的对应位置上的值。 具体来说,Reducer遍历所有的value列表,找到属于矩阵A和矩阵B的部分,分别累加它们对应的乘积结果。 ```java public class MatrixMultiplyReducer extends Reducer<IntPairWritable, Text, IntPairWritable, DoubleWritable> { @Override protected void reduce(IntPairWritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException { List<Double> aValues = new ArrayList<>(); List<Double> bValues = new ArrayList<>(); for(Text val : values){ String[] parts = val.toString().split(","); if(parts[0].equals("A")){ aValues.add(Double.parseDouble(parts[2])); }else{ bValues.add(Double.parseDouble(parts[2])); } } double result = 0; for(double aVal : aValues){ for(double bVal : bValues){ result += aVal * bVal; } } context.write(key, new DoubleWritable(result)); } } ``` #### 自定义Writables 为了支持自定义类型的键(即由两部分组成),可以创建一个新的类继承`WritableComparable<T>`接口。 ```java public class IntPairWritable implements WritableComparable<IntPairWritable>{ private int first; private int second; public IntPairWritable() {} public IntPairWritable(int first, int second){ set(first,second); } public void set(int first,int second){ this.first = first; this.second = second; } public int getFirst(){ return first; } public int getSecond(){ return second; } @Override public void write(DataOutput out) throws IOException { out.writeInt(first); out.writeInt(second); } @Override public void readFields(DataInput in) throws IOException { first = in.readInt(); second = in.readInt(); } @Override public int compareTo(IntPairWritable other) { int cmp = Integer.compare(this.first,other.getFirst()); if(cmp != 0){ return cmp; } return Integer.compare(this.second,other.getSecond()); } } ``` 通过以上代码实现了基本的矩阵相乘功能[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值