P1224 NOI2013 向量內積

2022-05-19 07:50:16 字數 1828 閱讀 3555

傳送門

發現這個內積和矩乘有點像,考慮構造乙個 $n$ 行 $m$ 列的矩陣 $a$,每一行都是乙個題目給定的 $m$ 維向量

設 $b=aa^t$ ,其中 $a^t$ 為 $a$ 的轉置矩陣,那麼對於 $b_$ 的值,它其實就是向量 $i$ 和向量 $j$ 的內積

注意到 $k$ 只有 $2$ 或 $3$,先考慮 $k=2$ 時的情況

此時就是問矩陣 $b$ 在模 $2$ 意義下是否有位置的值為 $0$ ,並且求出位置

首先判斷是否有 $0$ ,因為此時 $b$ 的元素不是 $0$ 就是 $1$ ,所以就是比較 $b$ 和全 $1$ 矩陣 $c$ 是否相等

所以就是要快速判斷 $aa^t=c$ ,至於快速判斷矩陣乘積結果是否等於給定矩陣,是有套路的

設 $d$ 為 $1$ 行 $n$ 列的隨機矩陣,那麼如果 $daa^t \neq dc$ 那麼顯然 $aa^t \neq c$,否則還有概率是因為 $d$ 的影響才相等,我們多做幾次判斷即可

這樣矩乘的複雜度就會低很多,判斷 $daa^t$ 是否等於 $dc$ 時,如果 $dc$ 的第 $i$ 個位置和 $daa^t$ 不相等,那麼說明向量 $i$ 和某個向量內積不是 $k$ 的倍數,此時我們只要列舉另乙個向量 $j$ 並暴力判斷即可

對於 $k=3$ 的情況,發現 $b$ 的元素不只是 $0,1$ 還有 $2$ ,似乎沒法判斷了

但是注意到(我也不知道怎麼注意到的) $2^2 \equiv 1 \mod 3,1^2 \equiv 1 \mod 3,0^2 \equiv 0 \mod 3$ 

所以如果我們能把 $b$ 的每個元素平方,那麼 $b$ 就又變成了 $01$ 矩陣,直接列舉元素再平方顯然會 $t$ 飛

所以寫寫式子, $b_=a_i \cdot a_j=\sum_^a_ \cdot a_$,$(b_)^2=(\sum_^a_ \cdot a_)(\sum_^a_ \cdot a_)$

$(b_)^2=\sum_^\sum_^(a_a_)(a_a_)$

所以我們把向量變成 $m^2$ 維,$a'_=a_ \cdot a_$

然後就可以用同樣的方法判斷了,當然 $a'$ 不能直接生成,我們只能存一下 $x=(k_1-1)*m+k_2$ 時的 $k_1,k_2$ 乘的時候再利用 $a_,a_$ 進行計算

#include#include

#include

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;inline

intread()

while(ch>='

0'&&ch<='

9')

return x*f;

}const

int n=1e5+7,m=107

;int

n,m,k;

inline

int fk(int x)

inta[n][m],b[n],c[n],d[n];

inline

bool check(int i,int

j)inline

int find(int

p)void

solve1()

}printf(

"-1 -1\n");

}int

l[n],r[n];

void

solve2()

for(int i=1;i<=10;i++)

}printf(

"-1 -1\n");

}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 向量內積

兩個 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 的倍數。請幫助她解決這個問題。第一行包含 ...