Live2D

题解 向量内积

题目传送门

Description

两个 \(d\) 维向量 \(A=[a_1, a_2 ,...,a_d]\)\(B=[b_1 ,b_2 ,...,b_d]\) 的内积为其相对应维度的权值的乘积和,即:

\[(A,B) = \displaystyle \sum_{i=1}^d{a_ib_i} = a_1b_1 + a_2b_2 + \ldots + a_db_d \]

现有 \(n\)\(d\) 维向量 \(x_1, \ldots, x_n\),小喵喵想知道是否存在两个向量的内积为 \(k\) 的倍数。请帮助她解决这个问题。

第一行包含 \(3\) 个正整数 \(n,d,k\),分别表示向量的个数、维数以及待检测的倍数。

接下来 \(n\) 行每行有 \(d\) 个非负整数,其中第 \(i\) 行的第 \(j\) 个整数表示向量 \([x_i]\) 的第 \(j\) 维权值 \(x_{i,j}\)

包含两个整数,用空格隔开。

如果存在两个向量 \(x_p,x_q\) 的内积为 \(k\) 的整数倍,则输出两个向量的编号 \(p\)\(q\)(要求 \(p<q\))。如果存在多组这样的向量组合,输出其中任意一组即可。

若不存在这样的向量组合,则输出两个 \(-1\)

测试点编号 \(n\) \(d\) \(k\) \(x_i\)
\(1\) \(2\) \(20\) \(2\) \(\le 10\)
\(2\) \(5\) \(20\) \(2\) \(\le 10\)
\(3\) \(10\) \(20\) \(3\) \(\le 10\)
\(4\) \(20\) \(20\) \(2\) \(\le 100\)
\(5\) \(50\) \(20\) \(3\) \(\le 100\)
\(6\) \(50\) \(50\) \(2\) \(\le 1000\)
\(7\) \(50\) \(50\) \(3\) \(\le 3000000\)
\(8\) \(80\) \(80\) \(2\) \(\le 2000000\)
\(9\) \(100\) \(100\) \(3\) \(\le 3000000\)
\(10\) \(500\) \(100\) \(3\) \(\le 3000000\)
\(11\) \(1000\) \(100\) \(2\) \(\le 2000000\)
\(12\) \(1000\) \(100\) \(3\) \(\le 3000000\)
\(13\) \(10000\) \(100\) \(2\) \(< 10\)
\(14\) \(10000\) \(100\) \(3\) \(< 10\)
\(15\) \(15000\) \(100\) \(2\) \(< 10\)
\(16\) \(18000\) \(100\) \(2\) \(< 10\)
\(17\) \(20000\) \(100\) \(2\) \(< 10\)
\(18\) \(50000\) \(30\) \(3\) \(< 10\)
\(19\) \(80000\) \(30\) \(3\) \(< 10\)
\(20\) \(100000\) \(30\) \(3\) \(< 10\)

Solution

考虑到正经做法不是很好做,考虑不太正经的做法。

首先可以发现 \(k\le 3\),那么先考虑 \(k=2\) 时候的情况。可以发现,如果对于 \(i\) 存在:

\[\sum_{j=1}^{i-1}|x_i·x_j| \not\equiv i-1 \pmod 2 \]

就说明一定存在一个解了。正确概率不是很会算。快速算的话,可以对向量做个前缀和。

考虑 \(k=3\) ,你发现 \(x^{k-1}\equiv \pmod k\)\(k\) 为质数),所以如果对于 \(i\) 存在:

\[\sum_{j=1}^{i-1}|x_i·x_j|^2\not\equiv i-1\pmod 2 \]

那么也说明一定存在一个解了。这个也可以用前缀和算,复杂度 \(\Theta(nd^2)\)

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXN 100005
#define MAXM 105

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}

int n,d,mod,s[MAXN][MAXM],ind[MAXN],s1[MAXM],s2[MAXM][MAXM];

signed main(){
//	freopen ("P1224_18.in","r",stdin);
	srand (20050913); 
	read (n,d,mod);
	for (Int i = 1;i <= n;++ i) for (Int j = 1;j <= d;++ j) read (s[i][j]),s[i][j] %= mod;
	for (Int i = 1;i <= n;++ i) ind[i] = i;
	for (Int times = 1;times <= 1;++ times){
		random_shuffle(ind + 1,ind + n + 1);
		if (mod == 2){
			memset (s1,0,sizeof (s1));
			for (Int i = 1;i <= n;++ i){
				int ans = 0;
				for (Int j = 1;j <= d;++ j) ans ^= s[ind[i]][j] & s1[j],s1[j] ^= s[ind[i]][j];
				if (ans == (i - 1) % mod) continue;
				for (Int j = 1;j < i;++ j){
					ans = 0;
					for (Int k = 1;k <= d;++ k) ans ^= s[ind[i]][k] & s[ind[j]][k];
					if (!ans){
						write (min (ind[i],ind[j])),putchar (' '),write (max (ind[i],ind[j])),putchar ('\n');
						return 0;
					}
				}
			}
		}
		else{
			memset (s2,0,sizeof (s2));
			for (Int i = 1;i <= n;++ i){
//				cout << i << endl;
				int ans = 0;
				for (Int k1 = 1;k1 <= d;++ k1)
					for (Int k2 = 1;k2 <= d;++ k2)
						(ans += s[ind[i]][k1] * s[ind[i]][k2] * s2[k1][k2]),
						(s2[k1][k2] += s[ind[i]][k1] * s[ind[i]][k2]);
				ans %= mod;
				if (ans == (i - 1) % mod) continue;
				for (Int j = 1;j < i;++ j){
					ans = 0;
					for (Int k = 1;k <= d;++ k) (ans += s[ind[i]][k] * s[ind[j]][k] % mod) %= mod;
					if (!ans){
						write (min (ind[i],ind[j])),putchar (' '),write (max (ind[i],ind[j])),putchar ('\n');
						return 0;
					}
				}
			}
		}
	}
	puts ("-1 -1");
	return 0;
} 
posted @ 2021-08-09 20:31  Dark_Romance  阅读(144)  评论(0编辑  收藏  举报