题意很简单,就是两个大矩阵相乘,然后求乘积。

用 Strassen算法 的话,当N的规模达到100左右就会StackOverFlow了

况且输入的数据范围可达到800,如果变量还不用全局变量的话连内存开辟都开不出来

 #pragma comment(linker, "/STACK:16777216")
#include <iostream>
#include <stdio.h>
#define ll long long
using namespace std; const int N=; //常量N用来定义矩阵的大小
int A[N][N],B[N][N],C[N][N]; //定义三个矩阵A,B,C
int A11[N][N],A12[N][N],A21[N][N],A22[N][N];
int B11[N][N],B12[N][N],B21[N][N],B22[N][N];
int C11[N][N],C12[N][N],C21[N][N],C22[N][N];
int M1[N][N],M2[N][N],M3[N][N],M4[N][N],M5[N][N],M6[N][N],M7[N][N];
int AA[N][N],BB[N][N],MM1[N][N],MM2[N][N]; void input(int n,int p[][N]) //矩阵输入函数
{
int i,j; for(i=;i<n;i++)
{
for(j=;j<n;j++)
cin>>p[i][j];
p[i][j] %= ;
}
} void output(int n,int C[][N]) //据矩阵输出函数
{
int i,j;
for(i=;i<n;i++)
{ for(j=;j<n;j++)
cout<<C[i][j]<<" ";
cout<<endl;
} } void MATRIX_MULTIPLY(int A[][N],int B[][N],int C[][N]) //按通常的矩阵乘法计算C=AB的子算法(仅做2阶)
{
int i,j,t;
for(i=;i<;i++) //计算A*B-->C
for(j=;j<;j++)
{
C[i][j]=; //计算完一个C[i][j],C[i][j]应重新赋值为零
for(t=;t<;t++)
C[i][j]=(int)(C[i][j]+A[i][t]*B[t][j]+(int))%(int);
}
} void MATRIX_ADD(int n,int X[][N],int Y[][N],int Z[][N]) //矩阵加法函数X+Y—>Z
{
int i,j;
for(i=;i<n;i++)
for(j=;j<n;j++)
Z[i][j]=(X[i][j]+Y[i][j]+(int))%(int);
} void MATRIX_SUB(int n,int X[][N],int Y[][N],int Z[][N]) //矩阵减法函数X-Y—>Z
{
int i,j;
for(i=;i<n;i++)
for(j=;j<n;j++)
Z[i][j]=(X[i][j]-Y[i][j]+(int))%(int); } void STRASSEN(int n,int A[][N],int B[][N],int C[][N]) //STRASSEN函数(递归)
{ int i,j;//,x; if (n==)
MATRIX_MULTIPLY(A,B,C);//按通常的矩阵乘法计算C=AB的子算法(仅做2阶)
else
{
for(i=;i<n/;i++)
for(j=;j<n/;j++) {
A11[i][j]=A[i][j];
A12[i][j]=A[i][j+n/];
A21[i][j]=A[i+n/][j];
A22[i][j]=A[i+n/][j+n/];
B11[i][j]=B[i][j];
B12[i][j]=B[i][j+n/];
B21[i][j]=B[i+n/][j];
B22[i][j]=B[i+n/][j+n/];
} //将矩阵A和B式分为四块 MATRIX_SUB(n/,B12,B22,BB);
STRASSEN(n/,A11,BB,M1);//M1=A11(B12-B22) MATRIX_ADD(n/,A11,A12,AA);
STRASSEN(n/,AA,B22,M2);//M2=(A11+A12)B22 MATRIX_ADD(n/,A21,A22,AA);
STRASSEN(n/,AA,B11,M3);//M3=(A21+A22)B11 MATRIX_SUB(n/,B21,B11,BB);
STRASSEN(n/,A22,BB,M4);//M4=A22(B21-B11) MATRIX_ADD(n/,A11,A22,AA);
MATRIX_ADD(n/,B11,B22,BB);
STRASSEN(n/,AA,BB,M5);//M5=(A11+A22)(B11+B22) MATRIX_SUB(n/,A12,A22,AA);
MATRIX_SUB(n/,B21,B22,BB);
STRASSEN(n/,AA,BB,M6);//M6=(A12-A22)(B21+B22) MATRIX_SUB(n/,A11,A21,AA);
MATRIX_SUB(n/,B11,B12,BB);
STRASSEN(n/,AA,BB,M7);//M7=(A11-A21)(B11+B12)
//计算M1,M2,M3,M4,M5,M6,M7(递归部分) MATRIX_ADD(N/,M5,M4,MM1);
MATRIX_SUB(N/,M2,M6,MM2);
MATRIX_SUB(N/,MM1,MM2,C11);//C11=M5+M4-M2+M6 MATRIX_ADD(N/,M1,M2,C12);//C12=M1+M2 MATRIX_ADD(N/,M3,M4,C21);//C21=M3+M4 MATRIX_ADD(N/,M5,M1,MM1);
MATRIX_ADD(N/,M3,M7,MM2);
MATRIX_SUB(N/,MM1,MM2,C22);//C22=M5+M1-M3-M7 for(i=;i<n/;i++)
for(j=;j<n/;j++)
{
C[i][j]=C11[i][j];
C[i][j+n/]=C12[i][j];
C[i+n/][j]=C21[i][j];
C[i+n/][j+n/]=C22[i][j];
} //计算结果送回C[N][N] } } int main()
{
int num;
int i,j,k,r;
while(scanf("%d",&num)!=EOF)
{
if(num % == )
{
input(num,A);
input(num,B); //录入数组 STRASSEN(num,A,B,C); //调用STRASSEN函数计算 output(num,C); //输出计算结果
}
else
{
for(i=; i<num; i++)
for(j=; j<num; j++)
cin >> A[i][j];
A[i][j] %= ;
//scanf("%d",&A[i][j]);
for(i=; i<num; i++)
for(j=; j<num; j++)
cin >> B[i][j];
B[i][j] %= ;
//scanf("%d",&B[i][j]);
for(i=;i<num;++i)
for(k=;k<num;++k)
{
r=A[i][k];
for(j=;j<num;++j)
C[i][j]=(C[i][j]+r*B[k][j])%;
}
for(i=; i<num; i++)
{
for(j=; j<num; j++)
cout << C[i][j] << ' ';
//printf("%d ",C[i][j]);
//printf("\n");
cout << endl;
}
}
}
return ;
}

Stack Over Flow Code

所有只能考虑一开始肯定会TLE的朴素算法。

想到结果矩阵中只能有三个数,0,1,2

如果存在大量的0,那么就是一个稀疏矩阵,关于稀疏矩阵,我想到:

稀疏矩阵乘法优化

只需要在第二层循环内,碰到当然数为0则跳过,因为计算结果肯定为0

提交上去。

TLE.....................ORZ

于是开始思考是不是算法的问题,感觉不太科学,过的人也很多,不会太难把。

一直跪到了比赛结束,题说别人也是对稀疏矩阵优化九过了,我在检查了下代码。

发现了一个至关重要的问题,就是我在大规模数据输入输出的时候使用了cin 和 cout

不多说了,贴后来AC的代码:

#pragma comment(linker, "/STACK:16777216")
#include <iostream>
#include <stdio.h>
#define ll long long
using namespace std; const int N=; //常量N用来定义矩阵的大小
int A[N][N],B[N][N],C[N][N]; //定义三个矩阵A,B,C
int main(){
int num;
int i,j,k,r;
while(scanf("%d",&num)!=EOF){
memset(C, , sizeof(C));
for(i=; i<num; i++){
for(j=; j<num; j++){
scanf("%d",&A[i][j]);
A[i][j] %= ;
}
}
for(i=; i<num; ++i){
for(j=; j<num; ++j){
scanf("%d",&B[i][j]);
B[i][j] %= ;
}
}
for(i=;i<num;++i){
for(k=;k<num;++k){
if(A[i][k] == ){
continue;
}
for(j=;j<num;++j)
C[i][j]=(C[i][j]+A[i][k]*B[k][j])%;
}
}
for(i=; i<num; i++){
for(j=; j<num; j++){
printf("%d",C[i][j]);
if(j != num -) printf(" ");
}
printf("\n");
}
}
return ;
}

2014 HDU多校弟五场J题 【矩阵乘积】的更多相关文章

  1. 2014 HDU多校弟六场J题 【模拟斗地主】

    这是一道5Y的题目 有坑的地方我已在代码中注释好了 QAQ Ps:模拟题还是练的太少了,速度不够快诶 //#pragma comment(linker, "/STACK:16777216&q ...

  2. 2014 HDU多校弟五场A题 【归并排序求逆序对】

    这题是2Y,第一次WA贡献给了没有long long 的答案QAQ 题意不难理解,解题方法不难. 先用归并排序求出原串中逆序对的个数然后拿来减去k即可,如果答案小于0,则取0 学习了归并排序求逆序对的 ...

  3. 2014 HDU多校弟九场I题 不会DP也能水出来的简单DP题

    听了ZWK大大的思路,就立马1A了 思路是这样的: 算最小GPA的时候,首先每个科目分配到69分(不足的话直接输出GPA 2),然后FOR循环下来使REMAIN POINT减少,每个科目的上限加到10 ...

  4. 2014 HDU多校弟八场H题 【找规律把】

    看了解题报告,发现看不懂 QAQ 比较简单的解释是这样的: 可以先暴力下达标,然后会发现当前数 和 上一个数 的差值是一个 固定值, 而且等于当前数与i(第i个数)的商, 于是没有规律的部分暴力解决, ...

  5. hdu多校第五场1005 (hdu6628) permutation 1 排列/康托展开/暴力

    题意: 定义一个排列的差分为后一项减前一项之差构成的数列,求对于n个数的排列,差分的字典序第k小的那个,n<=20,k<=1e4. 题解: 暴力打表找一遍规律,会发现,对于n个数的排列,如 ...

  6. 牛客多校第五场 J:Plan

    链接:https://www.nowcoder.com/acm/contest/143/J 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...

  7. hdu多校第五场1006 (hdu6629) string matching Ex-KMP

    题意: 给你一个暴力匹配字符串公共前缀后缀的程序,为你对于某个字符串,暴力匹配的次数是多少. 题解: 使用扩展kmp构造extend数组,在扩展kmp中,设原串S和模式串T. extend[i]表示T ...

  8. hdu多校第五场1002 (hdu6625) three arrays 字典树/dfs

    题意: 给你两个序列a,b,序列c的某位是由序列a,b的此位异或得来,让你重排序列ab,找出字典序最小的序列c. 题解: 如果能找到a,b序列中完全一样的值当然最好,要是找不到,那也尽量让低位不一样. ...

  9. hdu多校第五场1004 (hdu6627) equation 1 计算几何

    题意: 给你一个C,再给你n组a,b,让你求x取什么值的时候,$ \sum_{i=1}^n |a_i*x+b_i| =C $,要求求出解的个数,并用最简分数从小到大表示,如果有无穷多解,输出-1. 题 ...

随机推荐

  1. windows如何安装scrapy

    第一次写博客,有不好的地方请理解! 在linux下安装scrapy几行命令就搞定了,windows就是事多! 话不多说,我们直接进入主题: 1. 下载python.地址 https://www.pyt ...

  2. https tomcat 证书搭建

    首先生成证书说明 keytool -genkey -alias castest -keyalg RSA -keystore c:/keys/caskey 先让输入密码,密码必须记住,下面会用到 其中“ ...

  3. Delphi 类型转换函数(有几个函数没见过,FloatToStrF,FloatToText等等)

    Chr 将一个有序数据转换为一个ANSI字符 Ord 将一个有序类型值转换为它的序号 Round 转换一个实型值为四舍五入后的整型值 Trunc 转换一个实型值为小数截断后的整型值 Int 返回浮点数 ...

  4. Delphi 常用属性说明(超长)

    Delphi组件的常用事件Onclick——当单击时触发这个事件中的代码Onchange——当改变该组件内容时触发其中的代码Oncreate——当创建时触发这个事件中的代码Onclose——当关闭的时 ...

  5. QT全局热键(用nativeKeycode封装API,不跨平台)

    在网上找了很长时间,大家都提到了一个QT全局热键库(qxtglobalshortcut),支持跨平台.在这篇文章中,我将只展示出windows平台下全局热键的设置. 这里提供的方法是在MyGlobal ...

  6. C++_template_栈的链式存储及实现

    由于在C++数据结构中的代码不完整,特补全.等日后当工程库调用. 若有疑问,请留言. #include<iostream> using namespace std; template< ...

  7. HDOJ 1253 胜利大逃亡(bfs)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1253 思路分析:因为问题需要寻找到达终点的最短的距离(最短的步数),即在状态转换图上需要找出层次最浅的 ...

  8. SVN 让项目某些文件不受版本控制

    @echo On @Rem 删除SVN版本控制目录 @PROMPT [Com] @for /r . %%a in (.) do @if exist "%%a\.svn" rd /s ...

  9. js中函数参数基本类型和引用类型的区别

    高级程序设计中说明,所有函数的参数都是按值传递的. 基本类型 向参数传递基本类型的值时,被传递的值会被复制给对应的命名参数 function addTen(num){ num=+10; return ...

  10. IOS中的自动布局

    Autolayout是一种“自动布局”技术,专门用来布局UI界面 Autolayout能很轻松地解决屏幕适配问题 Autolayout的两条核心概念:   >1 参照:通过参照其他控件或父控件来 ...