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

用 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. c 语言简单计算器源码

    //  main.c //  计算器 //  Created by qianfeng on 14-7-15. //  Copyright (c) 2014年 ___FGY___. All rights ...

  2. JQuery 限制文本框只能输入数字和小数点

    $(function(){ /*JQuery 限制文本框只能输入数字*/ $(".NumText").keyup(function(){ $(this).val($(this).v ...

  3. 【图文教程】用“iz3d”软件将您的游戏打造为红蓝3D游戏。

    iz3d是一款能将普通3D游戏转换为红蓝3D游戏的软件.基本上支持所有游戏,或许没用过的人会认为这只是类似于播放器中的一个小功能,将平面图形做成“伪3D”红蓝效果. 实际上不是的,游戏与平面图的结构不 ...

  4. Spring RESTful服务接收和返回JSON最佳实践

    http://blog.csdn.net/prince_hua/article/details/12103501

  5. DropBox为什么一直那么红——靠用户体验,旗帜鲜明,它要保存的是你的重要随身资料,并且开放API

    链接:http://www.zhihu.com/question/19705960/answer/71742127来源:知乎 看到这个问题竟然从11年答到现在,有趣的是这几年里国内云存储行业变化也是蛮 ...

  6. 开源项目live555学习心得

      推荐:伊朗美女找丈夫比找工作难女人婚前一定要看清三件事 × 登录注册   疯狂少男-IT技术的博客 http://blog.sina.com.cn/crazyboyzhaolei [订阅][手机订 ...

  7. [转载]各种在线api地址

    J2SE1.7英文api地址: http://download.oracle.com/javase/7/docs/api/J2SE1.6英文api地址:  http://download.oracle ...

  8. 开源html5_kiwijs_helloworld

    本次须要的下载文件已经共享出来 网盘地址 由于我使用的是黑苹果系统, window我就无视了. 开发工具使用 网盘里的 dmg :Sublime Text 打开开发工具后在helloworld中找到 ...

  9. 利用Linux命令行进行文本按行去重并按重复次数排序

    最近杂事太多,正事进展缓慢.Fighting! linux命令行提供了非常强大的文本处理功能,组合利用linux命令能实现好多强大的功能.本文这里举例说明如何利用Linux命令行进行文本按行去重并按重 ...

  10. UISegmentedControl(分页控制器) AND UISlider(滑块控制器)

    - (void)viewDidLoad { [super viewDidLoad]; UIImageView * animatedImageView = [[UIImageView alloc]ini ...