矩陣乘法 NOI2013 向量內積

2021-07-14 10:00:41 字數 4738 閱讀 1897

兩個

d 維向量 a=

[a1,

a2,…

,ad]

與 b=[

b1,b

2,…,

bd] 的內積為其相對應維度的權值的乘積和,即:⟨a

,b⟩=

∑i=1

daib

i=a1

b1+a

2b2+

⋯+ad

bd現在有

n 個

d維向量 x1

,x2,

…,xn

,小喵喵想知道是否存在兩個向量的內積為

k 的倍數。請幫助她解決這個問題。

第一行包含

3個正整數 n,

d,k ,分別表示向量的個數,維數以及待檢測的倍數。

接下來

n 行每行有

d個非負整數,其中第

i 行的第

j個整數表示向量 xi

的第 j 維權值 xi

,j。包含兩個整數,用空格隔開。

如果存在兩個向量 xp

,xq 的內積為

k 的整數倍,則輸出兩個向量的編號 p與

q (要求

p<

q)。如果存在多組這樣的向量組合,輸出其中任意一組即可。

若不存在這樣的向量組合,則輸出兩個 −1

。input

3 5 2

1 0 1 0 1

1 1 0 1 0

0 1 0 1 1

output
2 3
explanation⟨x

1,x2

⟩=1 ,⟨x

1,x3

⟩=1 ,⟨x

2,x3

⟩=2 。

測試點編號

n dk

xi,j12

202≤10

25202

≤10310

20

3 ≤10

42020

2

≤100550

20

3

≤100650

50

2

≤1000750

50

3

≤3000000880

80

2

≤3000000

9100

100

3

≤3000000

10500

100

3

≤3000000

111000

100

2

≤3000000

121000

100

3

≤3000000

1310000

100

2

<

1014

10000

100

3

<

1015

15000

100

2

<

1016

18000

100

2

<

1017

20000

100

2

<

1018

50000

30

3

<

1019

80000

30

3

<

1020

100000

30

3

<10

時間限制:5s

空間限制:

256mb

注意:以下運算都在模k意義下

我們把這些向量看成乙個n×

d 的矩陣a

a=⎡⎣

⎢⎢⎢⎢

⎢x1,

1x2,

1⋮xn

,1x1

,2x2

,2⋮x

n,2x

1,3x

2,3⋮

xn,3

⋯⋯⋱⋯

x1,d

x2,d

⋮xn,

d⎤⎦⎥

⎥⎥⎥⎥

a 的轉置矩陣at

=⎡⎣⎢

⎢⎢⎢⎢

x1,1

x1,2

⋮x1,

nx2,

1x2,

2⋮x2

,nx3

,1x3

,2⋮x

3,n⋯

⋯⋱⋯x

n,1x

n,2⋮

xnn⎤

⎦⎥⎥⎥

⎥⎥令b

=a×a

t ,那麼bi

,j就表示xi

⋅xj ,如果

b 矩陣除了主對角線全部是1的話,顯然無解。

但是求出

b矩陣的時間顯然是o(

n2d)

,顯然是無法通過本題的。

我們令b

′ 為bi

,i=x

i⋅xi

,其餘元素為1的矩陣。 如果b

=b′的話,就無解。

我們再隨機找出乙個列向量

c (其實就是全是1,因為0沒用。。。)b×

c=b′

×ca×

at×c

=b′×

ca×(

at×c

)=b′

×cd=

at×c

我們可以用o(

nd) 的時間求出來,a×

d 也可以用o(

nd) 的時間求出來,b′

×c可以o(

n)求出。

然後比較a×

(at×

c)b′

×c這兩個列向量的每乙個元素是否相同,如果第i行的元素不相同,說明xi

肯定是答案只要,列舉找出xj

即可。

儘管有出錯的概率,但是這個演算法還是比較可靠的。

我們發現1×

1≡2×

2≡1(

mod3)

所以,我們令b=

(a∗a

t)2 其餘矩陣定義不變,那麼展開後會發現 a′

=⎡⎣⎢

⎢⎢⎢⎢

x1,1

×x1,

1x2,

1×x2

,1⋮x

n,1×

xn,1

x1,1

×x1,

2x2,

1×x2

,2⋮x

n,1×

xn,2

x1,1

×x1,

3x2,

1×x2

,3⋮x

n,1×

xn,3

⋯⋯⋱⋯

x1,1

×x1,

dx2,

1×x2

,d⋮x

n,1×

xn,d

x1,2

×x1,

1x2,

2×x2

,1⋮x

n,2×

xn,1

x1,2

×x1,

2x2,

2×x2

,2⋮x

n,2×

xn,2

⋯⋯⋱⋯

x1,d

×x1,

dx2,

d×x2

,d⋮x

n,d×

xn,d

⎤⎦⎥⎥

⎥⎥⎥b

=a′×

a′t

然後參考k=

2 的演算法即可,由於k=

3 時矩陣太大,記憶體開不下,但是算的時候按照規則算就行了。

#include

#include

using

namespace

std;

#define maxn 100000

#define maxm 100

int n,d,k,a[maxn+10][maxm+10],s[maxn+10],c[maxm*maxm+10],g[maxn+10];

void read(int &x)

}int get_id(int i,int j)

void read()

for(i=1;i<=n;i++)

s[i]%=k;

}void solve2()

for(j=1;j<=n;j++)

if(i!=j)

if(i>j)

swap(i,j);

printf("%d %d\n",i,j);

}void solve3()

for(j=1;j<=n;j++)

if(j!=i)

if(i>j)

swap(i,j);

printf("%d %d\n",i,j);

}int main()

NOI2013 向量內積

題面 題解窩本來想用這道題寫矩陣雜湊的,所謂矩陣雜湊,就是快速判斷兩個矩陣的乘積是不是另外乙個矩陣。矩陣雜湊就是隨機乙個向量,利用矩陣結合律先算向量和各矩陣的乘積,然後直接比較兩個向量是不是相等的。這樣本來是 n 3 的,就變成 n 2 的。但是看到題解第一種方法更簡便而且更易懂,就寫第一種方法了。...

NOI2013 向量內積

定義兩個 d 維向量 的內積為其相對應維度的權值的乘積和 a i b i 現在有 n 個 d 維向量,判斷是否存在兩個向量的內積為 k 的倍數 我們考慮將 n 個 d 維的向量構成乙個 n d 的矩陣 a a 為 a 的轉置矩陣。令矩陣 那麼 就表示了向量 i 與向量 j 的內積。直接判斷內積的值即...

NOI2013 向量內積(隨機好題)

先考慮 k 2 怎麼做。注意到點積不為0就為1。我們隨機乙個排列 p i 然後列舉 i 1 n 看看 p i 與 p 1.i 1 的點積和 s 如果 s i 1 mod k 則說明 p 1.i 1 中一定有乙個向量和 p i 的點積 0 此時暴力check就行了。最壞情況一次check的錯誤概率是 ...