2014 HDU多校弟五场J题 【矩阵乘积】
题意很简单,就是两个大矩阵相乘,然后求乘积。
用 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题 【矩阵乘积】的更多相关文章
- 2014 HDU多校弟六场J题 【模拟斗地主】
这是一道5Y的题目 有坑的地方我已在代码中注释好了 QAQ Ps:模拟题还是练的太少了,速度不够快诶 //#pragma comment(linker, "/STACK:16777216&q ...
- 2014 HDU多校弟五场A题 【归并排序求逆序对】
这题是2Y,第一次WA贡献给了没有long long 的答案QAQ 题意不难理解,解题方法不难. 先用归并排序求出原串中逆序对的个数然后拿来减去k即可,如果答案小于0,则取0 学习了归并排序求逆序对的 ...
- 2014 HDU多校弟九场I题 不会DP也能水出来的简单DP题
听了ZWK大大的思路,就立马1A了 思路是这样的: 算最小GPA的时候,首先每个科目分配到69分(不足的话直接输出GPA 2),然后FOR循环下来使REMAIN POINT减少,每个科目的上限加到10 ...
- 2014 HDU多校弟八场H题 【找规律把】
看了解题报告,发现看不懂 QAQ 比较简单的解释是这样的: 可以先暴力下达标,然后会发现当前数 和 上一个数 的差值是一个 固定值, 而且等于当前数与i(第i个数)的商, 于是没有规律的部分暴力解决, ...
- hdu多校第五场1005 (hdu6628) permutation 1 排列/康托展开/暴力
题意: 定义一个排列的差分为后一项减前一项之差构成的数列,求对于n个数的排列,差分的字典序第k小的那个,n<=20,k<=1e4. 题解: 暴力打表找一遍规律,会发现,对于n个数的排列,如 ...
- 牛客多校第五场 J:Plan
链接:https://www.nowcoder.com/acm/contest/143/J 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...
- hdu多校第五场1006 (hdu6629) string matching Ex-KMP
题意: 给你一个暴力匹配字符串公共前缀后缀的程序,为你对于某个字符串,暴力匹配的次数是多少. 题解: 使用扩展kmp构造extend数组,在扩展kmp中,设原串S和模式串T. extend[i]表示T ...
- hdu多校第五场1002 (hdu6625) three arrays 字典树/dfs
题意: 给你两个序列a,b,序列c的某位是由序列a,b的此位异或得来,让你重排序列ab,找出字典序最小的序列c. 题解: 如果能找到a,b序列中完全一样的值当然最好,要是找不到,那也尽量让低位不一样. ...
- hdu多校第五场1004 (hdu6627) equation 1 计算几何
题意: 给你一个C,再给你n组a,b,让你求x取什么值的时候,$ \sum_{i=1}^n |a_i*x+b_i| =C $,要求求出解的个数,并用最简分数从小到大表示,如果有无穷多解,输出-1. 题 ...
随机推荐
- Linux第三方源
由于版权等各方面原因,很多时候在基础安装完Linux后,满多软件并不包含在yum(对于Ubuntu可能是apt-get)源中. 因此可以去下载第三方源,安装下载第三方软件.当然,如果习惯了源代码编译安 ...
- 转;说说AngularJS中的$parse和$eval
说说AngularJS中的$parse和$eval AngularJS的初学者常常会对$parse和$eval两个内建服务感到有些困惑,今天我们就来说说AngularJS中的$parse和$eval. ...
- 从51跳cortex-m0学习2——程序详解
跳cortex-m0——思想转变>之后又一入门级文章,在此不敢请老鸟们过目.不过要是老鸟们低头瞅了一眼,发现错误,还请教育之,那更是感激不尽.与Cortex在某些操作方式上的异同,让自己对Cor ...
- 什么是PCB改板及PCB改板应注意的问题
PCB改板是指在保持原有功能一致的前提下,对原有产品设计及电路板布局走线设计的基础上进行整改设计,调整板上器件布局与线路走向,实现电子产品重新设计研发,同时又可以规避知识产权等纠纷,加快新产品研发速度 ...
- 关于Qt信号与槽机制的传递方向性研究(结论其实是错误的,但是可以看看分析过程)
最近由于项目的需求,一直在研究Qt.信号与槽机制是Qt的一大特色,该机制允许两者间传递参数,依次来实现对象间的通信.这个参数会分别存在于信号的参数列表和槽函数的参数列表中.需要注意的是,若将槽函数绑定 ...
- HDU 1720 A+B Coming
#include <string> #include <cstdio> #include <iostream> using namespace std; int c ...
- Android Animations动画使用详解
一.动画类型 Android的animation由四种类型组成:alpha.scale.translate.rotate XML配置文件中 alpha 渐变透明度动画效果 scale 渐变尺寸伸缩动画 ...
- UVA - 12230 Crossing Rivers (期望)
Description You live in a village but work in another village. You decided to follow the straight pa ...
- hadoop学习;安装jdk,workstation虚拟机v2v迁移;虚拟机之间和跨物理机之间ping网络通信;virtualbox的centos中关闭防火墙和检查服务启动
JDK 在Ubuntu下的安装 与 环境变量的配置 前期准备工作: 找到 JDK 和 配置TXT文件 并拷贝到桌面下 不是目录 而是文件拷贝到桌面下 以下的命令部分就直接复制粘贴就能够了 1.配 ...
- Sql缓存依赖--数据库缓存
•依赖于文件内容CacheDependency cDep = new CacheDependency(filePath); •依赖于数据库内容(轮询机制/通知机制)一:轮询机制 1.在数据库新建版本表 ...