[NOI2013] 向量内积

注意:本文中的一切数字即数字运算均在\(k\)的同余系内(即\(x\leftarrow x\bmod k\)),*只用于表示向量点积。

暴力的算法是,从小到大枚举向量\(A[x]\),判定\(A[1]\)\(A[x-1]\)中是否存在与\(A[x]\)点积为\(0\)的向量:若存在,暴力搜索答案;否则枚举下一个向量\(A[x+1]\)

算法的瓶颈在于“判定”这一部分,即计算\(\sum_{y<x}\sigma(A[y]*A[x]\not=0)\)是否等于\(x-1\)1

\(k=2\)时因为\(\sigma(w\not=0)=w\),所以只需判定下式值为\(x-1\)即可
\[ \sum_{y<x}A[x]*A[y]=A[x]*\sum_{y<x}A[y] \]
然后是\(k=3\)的情况,这时因为\(\sigma(w\not=0)=w^2\),所以只需判定下式值为\(x-1\)即可
\[ \sum_{y<x}(A[x]*A[y])^2 =\sum_{y<x}(\sum_iA[x,i]A[y,i])^2=\sum_{y<x}\sum_{i}A[x,i]A[y,i]\sum_jA[x,j]A[y,j]\\ =\sum_i\sum_jA[x,i]A[x,j]\sum_{y<x}A[y,i]A[y,j] \]
两种情况的式子都化简到了能快速处理的形式。

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

int n,m,K,id[100001];
int a[100001][101],b[101],c[101][101];

int solve(int x) {
    int tot=0;
    if(K==2) 
        for(int i=1; i<=m; b[i]^=a[x][i],i++) tot^=b[i]&a[x][i];
    else 
        for(int i=1; i<=m; ++i) 
        for(int j=1; j<=m; c[i][j]+=a[x][i]*a[x][j],++j) 
            tot+=c[i][j]*a[x][i]*a[x][j];
    return tot%K;
}
bool check(int x,int y) {
    int tot=0;
    for(int i=1; i<=m; ++i) tot+=a[x][i]*a[y][i];
    return tot%K==0;
}

int main() {
    scanf("%d%d%d",&n,&m,&K);
    for(int i=1; i<=n; ++i) 
    for(int j=1; j<=m; ++j) 
        scanf("%d",&a[i][j]),a[i][j]%=K;
    for(int i=1; i<=n; ++i) id[i]=i;
    for(int OVO=5; OVO--; ) {
        random_shuffle(id+1,id+n+1);
        K==2?memset(b,0,sizeof b):memset(c,0,sizeof b);
        for(int i=1; i<=n; ++i) if(solve(id[i])!=(i-1)%K) 
        for(int j=1; j<i; ++j) if(check(id[i],id[j])) {
            if(id[i]>id[j]) swap(id[i],id[j]);
            printf("%d %d\n",id[i],id[j]);
            return 0;
        }
    }
    puts("-1 -1");
    return 0;
}

  1. 这一定正确吗?拿衣服 当然不。注意此时的式子实际上是\(\sum\dots\equiv x-1\pmod k\)这样,所以这样判断是存在错判概率的。一个解决办法是把向量顺序打乱多做几次。

转载于:https://www.cnblogs.com/nosta/p/10875713.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值