【bzoj2396】神奇的矩阵 随机化

矩阵乘法随机化验证
本文介绍了一种通过随机化方法来验证两个矩阵相乘的结果是否等于第三个矩阵的方法。该方法利用了矩阵乘法的结合律特性,并通过多次随机试验进行验证。

题目描述

给出三个行数和列数均为N的矩阵A、B、C,判断A*B=C是否成立。

输入

题目可能包含若干组数据。
对于每组数据,第一行一个数N,接下来给出三个N*N的矩阵,依次为A、B、C三个矩阵。

输出

对于每组数据,若A*B=C成立,则输出Yes,否则No。每个答案占一行。

样例输入

1
2
2
100

样例输出

No


题解

随机化

如果直接把$A$与$B$的乘积算出来肯定会GG。。

考虑,如果$A*B=C$,那么$T*(A*B)=T*C$,而矩阵乘法具有结合律,因此有$(T*A)*B=T*C$。如果取$T$为$1*n$的行向量,那么每一步矩阵乘法的复杂度都是$O(n^2)$的。

于是可以使用这种方法大致判断出$A*B$是否等于$C$。随机出$T$矩阵,然后判断$(T*A)*B$与$T*C$是否相等即可。大约每组数据随机10次即可出解。

#include <cstdio>
#include <algorithm>
#define N 1010
using namespace std;
typedef long long ll;
ll a[N][N] , b[N][N] , c[N][N] , t[N] , v[N];
bool judge(int n)
{
	int cnt , i , j;
	ll sb , sc;
	for(cnt = 1 ; cnt <= 10 ; cnt ++ )
	{
		for(i = 1 ; i <= n ; i ++ ) t[i] = rand() % 999 + 1;
		for(i = 1 ; i <= n ; i ++ )
			for(v[i] = 0 , j = 1 ; j <= n ; j ++ )
				v[i] += t[j] * a[j][i];
		for(i = 1 ; i <= n ; i ++ )
		{
			for(sb = sc = 0 , j = 1 ; j <= n ; j ++ )
				sb += v[j] * b[j][i] , sc += t[j] * c[j][i];
			if(sb != sc) return 0;
		}
	}
	return 1;
}
int main()
{
	srand(20011011);
	int n , i , j;
	while(~scanf("%d" , &n))
	{
		for(i = 1 ; i <= n ; i ++ )
			for(j = 1 ; j <= n ; j ++ )
				scanf("%lld" , &a[i][j]);
		for(i = 1 ; i <= n ; i ++ )
			for(j = 1 ; j <= n ; j ++ )
				scanf("%lld" , &b[i][j]);
		for(i = 1 ; i <= n ; i ++ )
			for(j = 1 ; j <= n ; j ++ )
				scanf("%lld" , &c[i][j]);
		if(judge(n)) puts("Yes");
		else puts("No");
	}
	return 0;
}

 

 

转载于:https://www.cnblogs.com/GXZlegend/p/7522542.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值