傳送門
發現這個內積和矩乘有點像,考慮構造乙個 $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 的倍數。請幫助她解決這個問題。第一行包含 ...