[BZOJ3243][Noi2013]向量内积(神奇的思路+随机化)

这思路真的神!

Source

https://www.lydsy.com/JudgeOnline/problem.php?id=3243

Solution

显然,此题的突破口在于: K=2 K = 2 3 3
先讨论 K=2 的情况。
思路:记前缀和 sum[i] s u m [ i ] ,表示前 i i 个向量之和。如果对于第 i 个向量,满足条件 p p

1j<i,(Xj,Xi)mod2=1

那么一定就满足条件 q q
(sum[i1],Xi)i1(mod2)

因此 q ┐ q p ┐ p 的充分而非必要条件。
找到一个满足 q ┐ q i i 后,在 1j<i 范围内找到对应的 j j ,那么 j i i 一定是一组合法解。
为了降低错误的概率,可多次将向量随机打乱顺序。
K=3 时,
思路为: 12221(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 为:
j=1dk=1dsum[i1][j][k]×Xi,j×Xi,ki1(mod3)

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值