P1224 [NOI2013] 向量内积(矩阵乘法&随机化)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1224 [NOI2013] 向量内积(矩阵乘法&随机化)相关的知识,希望对你有一定的参考价值。

P1224 [NOI2013] 向量内积(矩阵乘法&随机化)

k = 2 k=2 k=2

考虑维护前 i − 1 i-1 i1个向量的前缀和。

将其与第 i i i个向量进行求内积,若不等于 k − 1 k-1 k1,则必然存在第 i i i项与其内积为 0 0 0满足条件,然后就暴力找即可。

每次特判的复杂度是 O ( d ) O(d) O(d)的,若找到了必定在 O ( n d ) O(nd) O(nd)的范围内可以找到。

k = 3 k=3 k=3时,考虑 1 2 ≡ 2 2 ( m o d 3 ) 1^2\\equiv 2^2\\pmod{3} 1222(mod3)

则我们可以维护 c [ i ] [ j ] = ∑ j = 1 i − 1 a j x a j y \\large c[i][j]= \\sum\\limits_{j=1}^{i-1} a_{jx}a_{jy} c[i][j]=j=1i1ajxajy

因为 ( ∑ k = 1 d a i k a j k ) 2 = ∑ k 1 d ∑ k 2 d a i k 1 a j k 1 a i k 2 a j k 2 \\large (\\sum\\limits_{k=1}^{d} a_{ik}a_{jk})^2=\\sum\\limits_{k_1}^d\\sum\\limits_{k_2}^da_{ik_1}a_{jk_1}a_{ik_2}a_{jk_2} (k=1daikajk)2=k1dk2daik1ajk1aik2ajk2

在这里插入图片描述

所以维护一个 c [ i ] [ j ] c[i][j] c[i][j]的前缀和即可。

每次随机化一下 i d id id,减少失败概率。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll; 
const int N=101000,M=111,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define rg register
inline int read(){
	int res=0;
	char ch=getchar(),ch1=ch;
	while(!isdigit(ch))ch1=ch,ch=getchar();
	while(isdigit(ch))
		res=(res<<3)+(res<<1)+ch-'0',ch=getchar();
	return ch1=='-'?-res:res;
}
int a[N][M],b[M],c[M][M];
int n,mo,d;
inline bool ck(int x,int y){
	int s=0;
	for(rg int i=1;i<=d;i++) s+=a[x][i]*a[y][i];
	return s%mo; 
}
inline int f(int x){
	int s=0;
	if(mo==2){
		for(rg int i=1;i<=d;b[i]^=a[x][i],++i)
			s^=a[x][i]&b[i];
	}
	else {
		for(rg int i=1;i<=d;i++)
			for(rg int j=1;j<=d;c[i][j]+=a[x][i]*a[x][j],j++)
				s+=a[x][i]*a[x][j]*c[i][j]%mo;
	}
	return s%mo;
}
int id[N];
int main(){
	n=read(),d=read(),mo=read();
	for(rg int i=1;i<=n;++i){
		id[i]=i;
		for(rg int j=1;j<=d;++j)
			a[i][j]=read()%mo;
	}
	for(rg int T=0;T<6;T++){
		mo==2?mst(b,0):mst(c,0);
		random_shuffle(id+1,id+n+1);
		for(rg int i=1;i<=n;++i)
			if(f(id[i])!=(i-1)%mo)
				for(rg int j=1;j<i;++j){
					if(!ck(id[i],id[j])){
						if(id[i]>id[j]) swap(i,j);
						return printf("%d %d\\n",id[i],id[j]),0;
					}
				}
	}
	puts("-1 -1");
	return 0;
}

以上是关于P1224 [NOI2013] 向量内积(矩阵乘法&随机化)的主要内容,如果未能解决你的问题,请参考以下文章

R语言矩阵向量操作(矩阵乘法,向量内积外积(叉乘),矩阵转置,矩阵的逆)

R语言矩阵向量操作(矩阵乘法,向量内积外积(叉乘),矩阵转置,矩阵的逆)

bzoj 3243: [Noi2013]向量内积

[Noi2013]向量内积

uoj121 NOI2013—向量内积

矩阵乘法