这思路真的神!
Source
https://www.lydsy.com/JudgeOnline/problem.php?id=3243
Solution
显然,此题的突破口在于:
K=2
K
=
2
或
3
3
。
先讨论 的情况。
思路:记前缀和
sum[i]
s
u
m
[
i
]
,表示前
i
i
个向量之和。如果对于第 个向量,满足条件
p
p
:
那么一定就满足条件 q q :
因此 ┐q ┐ q 是 ┐p ┐ p 的充分而非必要条件。
找到一个满足 ┐q ┐ q 的 i i 后,在 范围内找到对应的 j j ,那么 和 i i 一定是一组合法解。
为了降低错误的概率,可多次将向量随机打乱顺序。
时,
思路为: 12≡22≡1(mod3) 1 2 ≡ 2 2 ≡ 1 ( mod 3 )
所以将向量平方之后做一样的事情。设:
sum[i][j][k]=∑h=1iXh,j×Xh,k
s
u
m
[
i
]
[
j
]
[
k
]
=
∑
h
=
1
i
X
h
,
j
×
X
h
,
k
那么这时的条件 q q 为:
和 K=2 K = 2 一样的处理方法。
Code
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
using namespace std;
inline int read() {
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
const int N = 1e5 + 5, L = 105, M = 1e4 + 5;
int n, d, PYZ, a[N][L], sum[M];
int main() {
int i, j, k; n = read(); d = read(); PYZ = read();
For (i, 1, n) For (j, 1, d) a[i][j] = read() % PYZ;
For (i, 1, d * d) sum[i] = 0; For (i, 1, n) {
int sp = 0; if (PYZ == 2) For (j, 1, d) sp = sp ^ (sum[j] & a[i][j]);
else For (j, 1, d) For (k, 1, d) {
int x = (j - 1) * d + k;
sp = (sp + a[i][j] * a[i][k] * sum[x]) % 3;
}
if (sp != (i - 1) % PYZ) For (j, 1, i - 1) {
int rp = 0; For (k, 1, d) rp = (rp + a[j][k] * a[i][k]) % PYZ;
if (!rp) {
if (i > j) swap(i, j); return printf("%d %d", i, j), 0;
}
}
if (PYZ == 2) For (j, 1, d) sum[j] ^= a[i][j];
else For (j, 1, d) For (k, 1, d) {
int x = (j - 1) * d + k;
sum[x] = (sum[x] + a[i][j] * a[i][k]) % PYZ;
}
}
puts("-1 -1"); return 0;
}