题意
给定 \(n\) 个 \(d\) 维向量 \(a_i\),求一对合法的 \(i,j\) 使得 \(a_i\cdot a_j=0\),其中 \(\cdot\) 是向量点积,即 \(a_i\cdot a_j=\sum_{p=1}^d a_{i,p}a_{j,p}\)。
\(n\le 10^5,d\le 30,2\le k\le 3\)
分析
考虑 \(k=2\) 怎么做。发现寻找一组解比较困难,考虑随机化。若无解,那么肯定满足 \(\forall i,j, a_i\cdot a_j\equiv 1\)。考虑随出一个集合 \(S\),并让集合 \(S\) 外的 \(i\) 与 \(S\) 内的所有向量分别做点积并求和(模 \(k\) 意义下),若总和为 \(|S|\bmod k\),则这个 \(i\) 肯定与 \(S\) 内的某个点点乘后合法,暴力 check 即可。不难发现每次做一遍成功率至少为 \(\frac{1}{2}\),多做几次即可。复杂度 \(O(Knd)\),\(K\) 为随机次数。
考虑 \(k=3\)。这时无解,点积的结果可能为 \(1\) 或 \(2\),相当的不好处理。但是注意到 \(1\) 和 \(2\) 平方后的结果模 \(3\) 意义下均为 \(1\),把 \(\sum_{p=1}^d a_{i,p}a_{j,p}\) 转化为 \(\sum_{p=1}^d\sum_{q=1}^d a_{i,p}a_{i,q}a_{j,p}a_{j,q}\),这样就转化为了 \(d\leftarrow d^2\) 的 \(k=2\),就好处理了。复杂度 \(O(Knd^2)\)。
int n,m,d,k;
int a[maxn][maxm],b[maxms];
mt19937 rnd(time(0));
bool flag[maxn];
inline int get(int x,int y){return a[x][y/d]*a[x][y%d];
}
inline void solve_the_problem(){n=rd(),d=rd(),k=rd(),m=d*d;rep(i,1,n)rep(j,0,d-1)a[i][j]=rd()%k;rep(_,1,B){int tot=0;rep(i,1,n)flag[i]=rnd()%2,tot+=flag[i];rep(j,0,m-1)b[j]=0;rep(i,1,n)if(flag[i])rep(j,0,m-1)b[j]=(b[j]+get(i,j))%k;rep(i,1,n)if(!flag[i]){int sum=0;rep(j,0,m-1)sum=(sum+get(i,j)*b[j])%k;if(sum!=tot%k){rep(l,1,n)if(flag[l]){sum=0;rep(j,0,m-1)sum=(sum+get(i,j)*get(l,j))%k;if(!sum)return printf("%d %d",min(i,l),max(i,l)),void();}}}}printf("-1 -1");
}