[NOI2013] vector inner product

Posted by greip on Mon, 27 Dec 2021 01:58:04 +0100

subject

Portal to LOJ

thinking

This question is really, really, really, really outrageous. Better from k = 2 k=2 k=2 start.

First of all, we need to think of such a thing: multiple vectors and multiple vectors, find the dot product in pairs, which is actually matrix multiplication, row vector times column vector.

Then, put all the row vectors together into a matrix A A A. We just need to find out A A T AA^T AAT is 0 0 Location of 0. No, it shouldn't be finding, but finding any one. Obviously, this operation is in modulo 2 2 2 in the sense of.

So we remember This problem , try moving here. What is the situation without solution? It's a matrix B B B. Satisfied B i , i = x i ⋅ x i B_{i,i}={\bf x}_i\cdot{\bf x}_i Bi,i = xi ⋅ xi, other positions are 1 1 1.

Random column vector C C C. To judge A ( A T C ) A(A^TC) Is A(ATC) equal to B B B . If not equal to B B B. Where are the different locations? If so B i , j B_{i,j} Bi,j do not match, multiply by one C j C_{j} Cj , contributed to the second i i i bit. (of course, one problem we find here is, C j = 0 C_j=0 Cj = 0 will make this difference ignored. But it's a mold 2 2 2, so there must be one C j C_j Cj all 1 1 1.)

So we find that the final column vector is the second i i If i is different, it must be the second i i A value of line i is 0 0 0, then x i {\bf x}_i xi , can be locked. Just enumerate another one. although B B B matrix is n × n n\times n n × N, you can't find it, but because it's special, B × C B\times C B × C can be calculated directly. Time complexity O ( n d ) \mathcal O(nd) O(nd) .

then k = 3 k=3 What about k=3? There seems to be no unique certainty B B B yes... But 1 2 ≡ 2 2 ≡ 1 ( m o d 3 ) 1^2\equiv 2^2\equiv 1\pmod{3} 12 ≡ 22 ≡ 1(mod3), so we can consider squaring it. How B i , j B_{i,j} Bi,j squared? I have to write my own formula, bad comment!

The third part of the final result x x x bit is
∑ i C i ⋅ ( ∑ j A x , j A j , i T ) 2 = ∑ j 1 , j 2 A x , j 1 A x , j 2 ∑ i C i A j 1 , i T A j 2 , i T \sum_{i}C_i\cdot \left(\sum_{j}A_{x,j}A^T_{j,i}\right)^2\\ =\sum_{j_1,j_2}A_{x,j_1}A_{x,j_2}\sum_{i}C_iA^T_{j_1,i}A^T_{j_2,i} i∑​Ci​⋅(j∑​Ax,j​Aj,iT​)2=j1​,j2​∑​Ax,j1​​Ax,j2​​i∑​Ci​Aj1​,iT​Aj2​,iT​

So we're going to preprocess the latter summation and write it as f ( j 1 , j 2 ) f(j_1,j_2) f(j1, j2), and then each x x x violence counts. Time complexity O ( n d 2 ) \mathcal O(nd^2) O(nd2) .

At this time, we looked back at the moon and felt that this thing seemed to have another understanding. a ⋅ b + a ⋅ c = a ⋅ ( b + c ) \bf a\cdot b+a\cdot c=a\cdot(b+c) A ⋅ b+a ⋅ c=a ⋅ (b+c), which is the distribution rate of dot product. So if a \bf a a and r r The dot products of r vectors are 1 1 1. So a \bf a a and this r r The dot product of the sum of r vectors should be r   m o d   2 r\bmod 2 rmod2 is right. We random a column vector, which is essentially a random set, then find the sum of the vectors in this set, and then find the dot product with each other vector to see whether it meets the standard.

So we have to be random a few more times. This thing is not very correct - if there are even numbers 0 0 0, the error cannot be detected.

I want to see others k = 3 k=3 What about k=3? It's not a simple distribution rate. But in fact, it's also simple. The square of the dot product is the corresponding multiplication in both dimensions, that is a i a j b i b j {\bf a}_i{\bf a}_j{\bf b}_i{\bf b}_j ai , aj , bi , bj, record when imitating the power of one power i i i. Here we record i , j i,j i,j . Similarly, each vector should be assigned a coefficient, then summed, and then "dot product" with each vector to see if it can match the whole vector 1 1 The value of 1.

code

This code actually has a small problem: when n n n very small, for example n = 3 n=3 When n=3, because r a n d o m    s h u f f l e \rm random\;shuffle Random shuffle instead of redoing r a n d \rm rand rand, it will be difficult to detect the problem.

#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long int_;
# define rep(i,a,b) for(int i=(a); i<=(b); ++i)
# define drep(i,a,b) for(int i=(a); i>=(b); --i)
inline int readint(){
	int a = 0; char c = getchar(), f = 1;
	for(; c<'0'||c>'9'; c=getchar())
		if(c == '-') f = -f;
	for(; '0'<=c&&c<='9'; c=getchar())
		a = (a<<3)+(a<<1)+(c^48);
	return a*f;
}
inline void writeint(int x){
	if(x > 9) writeint(x/10);
	putchar((x-x/10*10)^48);
}

int Mod, **vec, n, d;
int C[100000]; // random value
int tmp1[100], tmp2[100][100];
int self[100000]; // x_i.dot(x_i)
int check(){
	int sum = 0;
	rep(i,0,n-1) sum += C[i];
	if(Mod == 2){
		memset(tmp1,0,d<<2);
		rep(i,0,n-1) if(C[i]) rep(j,0,d-1)
			tmp1[j] ^= vec[i][j];
		for(int i=0,got; i<n; ++i){
			int want = sum+C[i]*(self[i]-1);
			rep(j,got=0,d-1)
				got ^= (tmp1[j]&vec[i][j]);
			if((want&1) != got) return i;
		}
	}
	else if(Mod == 3){
		memset(tmp2,0,d*30<<2);
		rep(i,0,n-1) if(C[i])
			rep(j,0,d-1) if(vec[i][j])
				rep(k,0,d-1) // two dimensions
					tmp2[j][k] += vec[i][j]
						*vec[i][k]*C[i];
		rep(j,0,d-1) rep(k,0,d-1)
			tmp2[j][k] %= 3; // %= Mod
		for(int i=0,got; i<n; ++i){
			int want = sum+C[i]*(
				self[i]*self[i]-1);
			want = (want%3+3)%3;
			rep(j,got=0,d-1) rep(k,0,d-1)
				got += tmp2[j][k]*
					vec[i][j]*vec[i][k];
			if(want != got%3) return i;
		}
	}
	return -1;
}

int main(){
	n = readint(), d = readint();
	Mod = readint();
	vec = new int*[n];
	rep(i,0,n-1){
		vec[i] = new int[d];
		rep(j,0,d-1){
			vec[i][j] = readint()%Mod;
			self[i] += vec[i][j]*vec[i][j];
		}
		self[i] %= Mod;
	}
	rep(i,0,n-1) C[i] = 1; // must
	int id = check();
	rep(i,0,n>>2) C[i] = 0; // 1/4
	if(Mod == 3) rep(i,0,n-1) ++ C[i];
	int sy = (Mod == 2) ? 100 : 10;
	for(; !(~id)&&sy; --sy){
		random_shuffle(C,C+n);
		id = check();
	}
	if(id == -1) puts("-1 -1");
	else{
		for(int i=0,got; i<n; ++i){
			if(i == id) continue;
			rep(j,got=0,d-1)
				got += vec[id][j]*vec[i][j];
			if(got%Mod == 0){
				writeint(min(id,i)+1);
				putchar(' ');
				writeint(max(id,i)+1);
				break; // done
			}
		}
		putchar('\n');
	}
	return 0;
}

Topics: C++ Math