[数学性质]luogu P1224 [NOI2013]向量内积

题面

https://www.luogu.com.cn/problem/P1224

分析

注意到k很小,只有2,3

对k值讨论

当k=2时,对于一个向量i,乘以之前向量的前缀和,如果之前向量与其乘积在模意义下都为1,值就为(i-1)%2,如果不为,则存在一个向量与其乘积在模意义下为0,O(nd)

当k=3时,余数为0,1,2,注意到对余数平方则余均为1,那么维护前缀平方和即可,O(nd^2)

当存在向量与其乘积为0时,找到对应向量的时间复杂度也为O(nd)

听他们说为了防止最坏情况(即一直到最后都没在前缀中找到和乘积为0的向量),需要randomshuffle一下序列。

代码

#include <iostream>
#include <cstdio>
using namespace std;
const int N=1e5+10;
const int D=101;
int n,d,k;
int a[N][D],t[N][D];

int main() {
    scanf("%d%d%d",&n,&d,&k);
    for (int i=1,x;i<=n;i++) {
        for (int j=1;j<=d;j++) scanf("%d",&a[i][j]),a[i][j]%=k;
        x=0;
        if (k==2)
            for (int j=1;j<=d;j++) (x+=t[0][j]*a[i][j])%=k,(t[0][j]+=a[i][j])%=k;
        else
            for (int j=1;j<=d;j++)
                for (int l=1;l<=d;l++) (x+=t[j][l]*a[i][j]*a[i][l])%=k,(t[j][l]+=a[i][j]*a[i][l])%=k;
        if (x!=(i-1)%k)
            for (int j=1;j<i;j++) {
                x=0;
                for (int l=1;l<=d;l++) (x+=a[i][l]*a[j][l])%=k;
                if (!x) return printf("%d %d",j,i),0;
            }
    }
    printf("-1 -1");
}
View Code
原文地址:https://www.cnblogs.com/mastervan/p/13854835.html