1. 程式人生 > 實用技巧 >[數學性質]luogu P1224 [NOI2013]向量內積

[數學性質]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