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

用 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. bzoj 1057: [ZJOI2007]棋盘制作 单调栈

    题目链接 1057: [ZJOI2007]棋盘制作 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 2027  Solved: 1019[Submit] ...

  2. 当x含有偶数个1,返回1,否则为0。

    题目描述: /* Return 1 when x contains an even number of 1s;0 otherwise. Assume W=32 */ int even_ones(uns ...

  3. 精通UNIX下C语言编程与项目实践

    cc  -I  //include 目录 -L //静态库目录?动态也可以 -l //小写L,接静态库名称?动态也可以 -DXXX='"XXFF"' //-D直接定义宏 -c 只编 ...

  4. 【转】vs2008中leptonica-1.68安装配置

    tesseract ocr挺不好配置的,找到一篇不错的文章,分享如下:http://hi.baidu.com/ever8936/blog/item/6998e1196b1d0161dab4bd8f.h ...

  5. 未能加载文件或程序集“xxxx”或它的某一个依赖项

    一般是解决方案中相互依赖的项目生成的目标平台不一样所致,更改为相同目标即可!

  6. 基于SIM 卡卡基不同制作工艺的研究

    1 国内外现行的SIM 卡卡基制作工艺 SIM 卡由卡基和芯片两部分组成.卡基上有植入芯片的台阶式芯片槽,SIM 卡的芯片通过多点焊接植入台阶式芯片槽之中与卡基组成SIM 卡,然后经过个性化数据处理, ...

  7. Protel99Se使用方法详解

    Protel99SE是应用于Windows9X/2000/NT操作系统下的EDA设计软件,采用设计库管理模式,可以进行联网设计,具有很强的数据交换能力和开放性及3D模拟功能,是一个32位的设计软件,可 ...

  8. zip文件压缩(转)

    zip文件结构            上面中的每一行都是一个条目,zip文件就是由一个或者多个条目组成.      条目在Java中对应ZipEntry类         创建zip压缩文件     ...

  9. powershell 生成随机用户信息

    #生成随机用户信息,包括姓名.QQ.邮箱,手机号 $nameArr=@('一','丁','三','专','世','业','丝','中','丰','临','丹','丽','举','乃','义', '乐' ...

  10. C++ 函数映射使用讲解

    想想我们在遇到多语句分支时是不是首先想到的是 switc case 和 if else if ... 这2种方式在编码方面确实简单少,但是当分支达到一定数量后,特别是分支内部有嵌套大段代码或者再嵌套分 ...